我可以安全地扩展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]
我可以安全地扩展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]
取决于您对“工作”的定义。
原型扩展有三个主要问题。
for .. in
它可以工作,Array.prototype
和Array
是可变的,所以你可以添加代码并调用属性。
然而:
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
+1 @Raynos我们可以随时指望您获得出色的JavaScript解答。 –
[Sugar.js](http://sugarjs.com/)专业。我认为它可以在受控环境(即您自己的Web应用程序)中受益,并且如果在图书馆中正确使用它也是可以接受的。 – Tomalak
@Tomalak拓展土着不是“坏”的。我默认情况下会这样做,最好放在'extendNatives'函数后面。如果你的库不是原生的对象扩展库,我认为在库中做这件事是不可接受的。作为库中的副作用扩展本地对象是不好的。扩展本地对象作为副作用的唯一可能情况是,如果它们填充ES5规范的一部分并且100%兼容,则可以接受。 – Raynos
安全,不是真的 - 因为你不能确定你延长他们的唯一一个,或者说你实际上延长了正确的方法(见原型 - 上次我检查,它扩展了内建类,这对其他脚本对内建行为的期望造成了严重破坏)。修改不属于你自己的对象是一条非常棘手的领土之路(“哦,但这是实际的内置concat()
,还是其他一些脚本改变它背后?”)。
参见例如这个更详细的讨论:http://perfectionkills.com/extending-built-in-native-objects-evil-or-not/
这是一种常见的做法,我相信它会在任何地方工作。尽管我不会作为答复发布,因为其他人可能能够确定它永远不会导致您的问题。 –
@Michael只是补充说Object.prototype是唯一一个不受限制的。任何使用'for..in'循环数组的人都应该被绊倒。我不会添加答案,因为我无法在所有浏览器上进行测试。 – Esailija
关于此主题的Andrew Dupont [给出了一个很好的JSConf演示文稿](http://blip.tv/jsconf/jsconf2011-andrew-dupont-everything-is-permitted-extending-built-ins-5211542)。 – Pointy