I have been reading the code of a few javascript libraries. I've noticed that AngularJS and Backbone.js both keep a local reference to array functions. e.g.:
var push = [].push // or array.push
what is the point of doing this when arrays are a construct of the language and should be accessible globally?
Because the Array prototype's functions can be applied to non-arrays.
For example, push
'ing items into an array-like object:
var o = { length: 0 };
[].push.call(o, 'hi');
o; //Object {0: "hi", length: 1}
Another common practice is slice
'ing the arguments
object into a native array:
(function() {
return [].slice.call(arguments); //[1, 2]
}(1, 2));
As you can see, saving references to these functions reduce the look up overhead, makes code smaller and minification-friendly.
In my opinion this is mostly for convenience and readability, as repeatedly writing [].arrayMethod
looks rather clunky. The performance and minification boosts are an extra.
Looking through Angular's source, here are the cases I've found:
push
is used in the JQLite prototype. Note that jQuery objects have array-like structures, similarly to the first example in this answer;slice
is used inside the sliceArgs
, concat
and bind
functions.Backbone also slice
s argument objects (at Events#trigger and Underscore methods proxying), it also uses slice
at Collection#slice.
I'm thinking library developers are especially keen on making their library resilient to the random things that might be happening on a page. If you get a reference to the correct Array.prototype.push early on and use closures to keep it out of reach of other code that you as a library writer are not aware of, it reduced the chances of (and makes it much easier to troubleshoot when) something unexpected happening if other code on the page decides to hijack this built-in method, which Javascript is very permissive of.
Consider:
function Library(){
var push=[].push;
var data=[];
this.save1=function(x){push.call(data, x);}
this.save2=function(x){data.push(x);}
this.get=function(){console.log(data);}
}
var o=new Library();
//Random on-page code
Array.prototype.push=function(x){console.info("doSomethingCrazy!");}
//Lets use the library functionality!
o.save1(1);
o.save2(2);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With