为什么Javascript库具有对数组方法的本地引用(推送,切片等等)?

时间:2013-11-16 06:31:44

标签: javascript angularjs backbone.js

我一直在阅读一些javascript库的代码。我注意到AngularJS和Backbone.js都保留了对数组函数的本地引用。例如:

var push = [].push  // or array.push

当数组是语言的结构并且应该可以全局访问时,这样做有什么意义呢?

3 个答案:

答案 0 :(得分:11)

因为Array原型的函数可以应用于非数组。

例如,push将项目放入类似数组的对象中:

var o  = { length: 0 };
[].push.call(o, 'hi');
o; //Object {0: "hi", length: 1}

另一种常见做法是slicearguments对象转换为本机数组:

(function() {
   return [].slice.call(arguments); //[1, 2]
}(1, 2));

正如您所看到的,保存对这些函数的引用可以减少查找开销,使代码更小并且更加简洁。

在我看来,这主要是为了方便和可读性,因为重复写[].arrayMethod看起来相当笨拙。性能和缩小提升是额外的。


通过Angular的来源,我发现了以下情况:

    {li> push用于JQLite prototype。请注意,jQuery对象具有类似于数组的结构,与此答案中的第一个示例类似;
  • slice用于sliceArgsconcatbind个功能。

Backbone还slice个参数对象(Events#triggerUnderscore methods proxying),它还在Collection#slice使用slice

答案 1 :(得分:3)

我认为图书馆开发人员特别热衷于让他们的图书馆能够适应页面上可能发生的随机事情。如果您在早期获得对正确的Array.prototype.push的引用并使用闭包来使其远离您作为库编写者不知道的其他代码,那么它会降低机会(并使其更容易如果页面上的其他代码决定劫持这种内置方法(Javascript非常宽松的话),则会发生意外情况。

考虑:

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);

答案 2 :(得分:0)

Douglas Crockford在其讲座The Metamorphosis of Ajax中指出的一个原因是,JavaScript库的开发人员可以有条件地添加实用程序方法,例如string.split之类的东西,这样它只会添加到对象的原型中如果它尚未由浏览器提供的标准库定义。