Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do Javascript Libraries have local references to array methods (push, slice, etc..)?

Tags:

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?

like image 955
ArtisanV Avatar asked Nov 16 '13 06:11

ArtisanV


2 Answers

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 slices argument objects (at Events#trigger and Underscore methods proxying), it also uses slice at Collection#slice.

like image 93
Fabrício Matté Avatar answered Sep 20 '22 02:09

Fabrício Matté


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);
like image 20
Fabio Beltramini Avatar answered Sep 19 '22 02:09

Fabio Beltramini