2011-11-24 72 views
2

我可以安全地扩展Javascript builtin类,如Array吗?我可以安全地扩展JavaScript内置类吗?

I.e.以下浏览器/环境将无法正常工作:

Array.prototype.double = function() { return this.concat(this); } 
Array.twice = function(a) { return a.double(); } 
Array.twice([1, 2, 3]) # => [1, 2, 3, 1, 2, 3] 
+1

这是一种常见的做法,我相信它会在任何地方工作。尽管我不会作为答复发布,因为其他人可能能够确定它永远不会导致您的问题。 –

+0

@Michael只是补充说Object.prototype是唯一一个不受限制的。任何使用'for..in'循环数组的人都应该被绊倒。我不会添加答案,因为我无法在所有浏览器上进行测试。 – Esailija

+0

关于此主题的Andrew Dupont [给出了一个很好的JSConf演示文稿](http://blip.tv/jsconf/jsconf2011-andrew-dupont-everything-is-permitted-extending-built-ins-5211542)。 – Pointy

回答

4

取决于您对“工作”的定义。

原型扩展有三个主要问题。

  • 它是全球范围,从而有名称冲突
  • 如果您添加枚举的属性它打破for .. in
  • 代码是混乱阅读,这是一个ES5功能或自定义库?

它可以工作,Array.prototypeArray是可变的,所以你可以添加代码并调用属性。

然而:

Array.prototype.trolls = 42; 
for (var k in []) { 
    alert(k === "trolls"); 
} 

以上是它打破for .. in的一个例子。这很容易用解决

Object.defineProperty(Array.prototype, "trolls", { 
    value: ..., 
    enumerable: false 
}); 

(ES5仅。在IE <符9.不能在传统的发动机中模拟)

for (var k in []) { 
    if ([].hasOwnProperty(k)) { 
    alert(k === "trolls"); 
    } 
} 

我个人避免自动延伸当地人这些确切的原因。但是我认为这是完全可以接受的有.extendNatives函数库中的像pd.extendNatives

+0

+1 @Raynos我们可以随时指望您获得出色的JavaScript解答。 –

+0

[Sugar.js](http://sugarjs.com/)专业。我认为它可以在受控环境(即您自己的Web应用程序)中受益,并且如果在图书馆中正确使用它也是可以接受的。 – Tomalak

+1

@Tomalak拓展土着不是“坏”的。我默认情况下会这样做,最好放在'extendNatives'函数后面。如果你的库不是原生的对象扩展库,我认为在库中做这件事是不可接受的。作为库中的副作用扩展本地对象是不好的。扩展本地对象作为副作用的唯一可能情况是,如果它们填充ES5规范的一部分并且100%兼容,则可以接受。 – Raynos

1

安全,不是真的 - 因为你不能确定你延长他们的唯一一个,或者说你实际上延长了正确的方法(见原型 - 上次我检查,它扩展了内建类,这对其他脚本对内建行为的期望造成了严重破坏)。修改不属于你自己的对象是一条非常棘手的领土之路(“哦,但这是实际的内置concat(),还是其他一些脚本改变它背后?”)。

参见例如这个更详细的讨论:http://perfectionkills.com/extending-built-in-native-objects-evil-or-not/

相关问题