【问题标题】:Can I safely extend javascript builtin classes?我可以安全地扩展 javascript 内置类吗?
【发布时间】:2011-11-24 21:43:58
【问题描述】:

我能否安全地扩展 Javascript 内置类,例如 Array

即以下内容在哪些浏览器/环境上不起作用:

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]

【问题讨论】:

  • 这是一种常见的做法,我相信它适用于任何地方。不过,我不会将其作为答案发布,因为其他人可能能够确定它永远不会给您带来问题。
  • @Michael 只是补充说Object.prototype 是唯一不受限制的。任何使用for..in 循环数组的人都应该被绊倒。我不会添加答案,因为我不可能在所有浏览器上进行测试。
  • Andrew Dupont gave a nice JSConf presentation 关于这个话题。
  • @Pierre 扩展 DOM 本身并不是一个“问题”。这更像是“仅限专家”的事情。 DOM-shim 做到了。

标签: javascript class


【解决方案1】:

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

原型扩展存在三个主要问题。

  • 它是全局范围,所以存在名称冲突
  • 如果您添加可枚举属性,它会破坏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 中的中断

或与

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

出于这些确切原因,我个人会避免自动扩展原生对象。但是我认为在你的库中拥有一个.extendNatives 函数是完全可以接受的,比如pd.extendNatives

【讨论】:

  • +1 @Raynos 我们总是可以指望您提供出色的 JavaScript 答案。
  • Sugar.js 专业地做到这一点。我认为它在受控环境(即您自己的网络应用程序)中可能是有益的,并且如果在图书馆中正确完成是可以接受的。
  • @Tomalak 扩展本地人并不“坏”。我不赞成默认这样做,最好放在extendNatives 函数后面。如果您的库不是本机对象扩展库,我认为在库中执行此操作是不可接受的。在库中扩展本机对象作为副作用是不好的。扩展原生对象作为副作用的唯一可能情况是,如果它们填充了 ES5 规范的一部分并且 100% 兼容。
  • 同意。不告诉任何人(即作为副作用)就这样做是一件坏事。
【解决方案2】:

安全,不是真的 - 因为你不能确定你是唯一扩展它们的人,或者你实际上正在扩展正确的方法(参见原型 - 我上次检查时,它正在扩展内置类,这对其他脚本对内置程序行为的期望造成了严重破坏)。修改你不拥有的对象是一个非常棘手的领域(“哦,但这是实际的内置concat(),还是其他脚本在我们背后改变了它?”)。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多