underscore.transparent

Push Underscore.js and Underscore.string functions to native JavaScript Objects. Yep! You have Sugar JS code styling but with Underscore

npm install underscore.transparent
25 downloads in the last month

Underscore.transparent Build Status

No one wants to dream about _, most people prefer $. -- (c) 2013 André Deudant

If you're too lazy to read and write _ character. Underscore.transparent is for you!

Old and boring _. syntax:

_.each(['zero', 'one', 'two'], function(element, index) { console.log(index+':'+element); });
=> "0:zero"
"1:one"
"2:two"

_.chain([2, 1, 3, [5, 8, 3, 9], null, false]).flatten().compact().uniq().shuffle().sort().value();
=> [1, 2, 3, 5, 8, 9]

_("   epeli  ").trim().capitalize();
=> "Epeli"

Becomes syntactic sugar:

['zero', 'one', 'two'].each(function(element, index) { console.log(index+':'+element); });
=> "0:zero"
"1:one"
"2:two"

[2, 1, 3, [5, 8, 3, 9], null, false].flatten().compact().uniq().shuffle().sort();
=> [1, 2, 3, 5, 8, 9]

"   epeli  ".trim().capitalize();
=> "Epeli"

Underscore.js is a utility-belt library for JavaScript that provides a lot of the functional programming support that you would expect in Prototype.js (or Ruby), but without extending any of the built-in JavaScript objects.

Underscore.transparent.js extends the built-in JavaScript objects with Underscore (and Underscore.string.js). So you can use Object-Oriented style and chaining with all Underscore and Underscore.string functions, without using the _ character (in the same way as Sugar library).

But modifying native objects... isn't it evil?

  • Quick answer: No!
  • For a longer answer read this excellent post.

Download

Installation and usage

In browsers

<script type="text/javascript" charset="utf-8" src="http://underscorejs.org/underscore-min.js"></script>

<!-- Optional Underscore.string integration -->
  <script type="text/javascript" charset="utf-8" src="https://raw.github.com/epeli/underscore.string/master/dist/underscore.string.min.js"></script>

<script type="text/javascript" charset="utf-8" src="https://raw.github.com/nowhereman/underscore.transparent/master/dist/underscore.transparent.min.js"></script>

<script type="text/javascript" charset="utf-8">
// <![CDATA[
  //Alias Underscore conflict functions
  _.mixin({
    encode: _.escape,
    decode: _.unescape,
    isNaNumber: _.isNaN
  });

  //Optional Underscore.string initialization
    _.mixin(_(_.str.exports()).extend({
      //Alias Underscore.string functions
      includeString: _.str.include,
      containsString: _.str.contains,
      reverseString: _.str.reverse
    }));
  // End of Optional

  //Init Underscore.transparent
  _.transparent();
// ]]>
</script>

bower installation

bower install underscore.transparent

Or add underscore.transparent to your apps component.json or bower.json.

  "dependencies": {
    "underscore.transparent": "latest"
  }

Node.js installation

npm package

npm install underscore.transparent

Configuration

Integrate with Underscore.js:

var _ = require('underscore');
//Alias Underscore conflict functions
_.mixin({
  encode: _.escape,
  decode: _.unescape,
  isNaNumber: _.isNaN
});

Optional Underscore.string integration:

// Import Underscore.string to separate object, because there are conflict functions (include, reverse, contains)
_.str = require('underscore.string');
// Mix in non-conflict functions and aliasing conflict functions to Underscore namespace, more info at https://github.com/epeli/underscore.string#readme
_.mixin(_(_.str.exports()).extend({
includeString: _.str.include,
containsString: _.str.contains,
reverseString: _.str.reverse
}));

Last but not least, init Underscore.transparent:

require('underscore.transparent');
//In Node.js we can safely extends all Underscore and Underscore.string functions to built-in JavaScript objects
_.transparent({extendAll: true, scope: global});

OMG _ is now transparent !

Caveats

Underscore conflict functions with window global object:

  • window.escape: Underscore.js doesn't have the same behaviour. You must use window.encode alias or Object.escape.
  • window.unescape: Underscore.js doesn't have the same behaviour. You must use window.decode alias or Object.unescape.
  • window.isNaN: Underscore.js doesn't have the same behaviour. isNaN(undefined) => true _.isNaN(undefined) => false. You must use window.isNaNumber alias or Object.isNaN.

Legacy browsers like IE 8 and below don't support correctly defineProperty function. For more info, read the last paragraph of this post. To prevent bugs in these browsers, Underscore.transparent don't add properties to Object.prototype by default.

You need to cast your objets to Hash class via Object.toHash or window.toHash or toHash function:

var obj1 = toHash({1:'one', 2:'two', 3:'three'});
obj1.each(function(element, index) { console.log(index+':'+element); })
=> "1:one"
"2:two"
"3:three"

Of course you can alias the toHash function with a shorter name:

var h = toHash; // alias of toHash function

var obj1 = h({1:'one', 2:'two', 3:'three'});
obj1.each(function(element, index) { console.log(index+':'+element); })
=> "1:one"
"2:two"
"3:three"

Inline Integer and Function calls need parenthesis:

(2).times(function(i) { console.log(i + ' times'); });

(function() { console.log("delayed during 1 sec."); }).delay(1000);

But generally, in real application code, you do:

var n = 2;
//...{some code}...
n.times(function(i) { console.log(i + ' times'); });

var myDelayedFunction = function() { console.log("delayed during 1 sec."); };
//...{some code}...
myDelayedFunction.delay(1000);

Due to JavaScript limitations, we lose some things:

  • Functions aren't available for undefined and null properties, null.values() trigger: "TypeError: null has no properties 'null.values()'" You need to use Object.values(null).
  • Calls like var s1 = "foobar"; s1.isString() aren't available to prevent unexpected bugs when the s1 variable is null, undefined or with isObject function. Instead, you should do Object.isString("foobar") or window.isString("foobar") (or isString("foobar"))
  • Native chaining don't work correctly for JavaScript functions who don't return the current object (E.g. Array.prototype.[push|pop|shift|unshift]). [2,1,3].shuffle().pop().sort(); => [] trigger "TypeError: (intermediate value).shuffle(...).pop(...).sort is not a function".

    In this case, you need to use chain and value functions: [2,1,3].chain().shuffle().pop().sort().value(); => [1,2]

More transparent functions

If you're application doesn't need to support IE 8 and below you can extend all Hash functions into Object.

_.transparent({extendAll: true});

So you can use Objects Underscore functions without toHash cast function:

var obj1 = {1:'one', 2:'two', 3:'three'};
obj1.each(function(element, index) { console.log(index+':'+element); })
=> "1:one"
"2:two"
"3:three"

Otherwise Object functions from examples will be available through Object.myFunction:

var obj1 = {1:'one', 2:'two', 3:'three'};
Object.each(obj1, function(element, index) { console.log(index+':'+element); })
=> "1:one"
"2:two"
"3:three"

Roadmap

Any suggestions or bug reports are welcome. Just open an issue.

Changelog

0.6.0

  • Add new functions and tests of Undercore.js between 1.4.4 and 1.5.2 versions
  • Add new functions and tests of Undercore.string.js between 2.3.1 and 2.3.3 versions

0.5.2

  • Fix IE8 and below when using function with implicit scope like isString("dd");.

0.5.1

  • Add newline at end of file underscore.transparent.js
  • Rewrite tests for _.transparent options with Mocha TDD interface and expect.js assertion library

0.5.0

  • is[Type] global functions are available for both Node.js and Web browsers
  • Add tests for _.transparent options

0.4.3

  • Fix Node.js usage
  • Fix Travis CI config
  • Better instructions in README.md

0.4.2

  • First public release !

Contribute

  • Fork & pull request. Don't forget about tests.
  • If you planning add some feature please create issue before.

Otherwise changes will be rejected.

Running tests

Open test/index.html file in your Web browser.

Without a Web browser, install PhantomJS and NPM, then:

npm test

Contributors list

Can be found here.

Licence

The MIT License

Copyright (c) 2013 Nowhere Man

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

npm loves you