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?
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?
Share Improve this question asked Nov 16, 2013 at 6:31 ArtisanVArtisanV 5114 silver badges14 bronze badges 2- I am assuming so that if the browser doesn't provide support for these functions, they can define such a function themselfs. I am not 100% sure about that though. – Sumurai8 Commented Nov 16, 2013 at 6:37
-
2
One possibility is that the newly declared
push
variable can be minimized to a one character name (reducing the minimized size of the library), but[].push
cannot be. – jfriend00 Commented Nov 16, 2013 at 7:03
3 Answers
Reset to default 11Because 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 mon 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 thesliceArgs
,concat
andbind
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);
One reason, noted by Douglas Crockford in his lecture The Metamorphosis of Ajax, is that developers of JavaScript libraries can conditionally add utility methods, for example something like string.split, such that it will only be added to an object's prototype if it is not already defined by the standard libraries provided by the browser.
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1740931226a4277053.html
评论列表(0条)