JavaScript:扩展元素原型

时间:2016-07-15 01:43:47

标签: javascript prototype element extending

我已经看到很多关于扩展Element的讨论。据我所知,这些是主要问题:

  • 可能与其他图书馆冲突
  • 它为DOM例程添加了未记录的功能
  • 它不适用于旧版IE
  • 可能与未来的变化相冲突

鉴于一个项目没有引用其他库,文档会发生变化,并且不会给历史浏览器带来任何影响:

是否有技术理由不扩展Element原型。以下是一个有用的示例:

Element.prototype.toggleAttribute=function(attribute,value) {
    if(value===undefined) value=true;
    if(this.hasAttribute(attribute)) this.removeAttribute(attribute);
    else this.addAttribute(attribute,value);
};

在没有提供合理解释的情况下,我看到了太多关于扩展原型的弊端的评论。

注1:上面的例子可能太明显了,因为toggleAttribute是将来可能添加的一种方法。对于讨论,假设它被称为manngoToggleAttribute

注2:我已经删除了该方法是否已存在的测试。即使这种方法已经存在,覆盖它也更容易预测。在任何情况下,我假设这里的要点是该方法尚未定义,更不用说实现了。这就是重点。

5 个答案:

答案 0 :(得分:2)

可以吗?技术上是的。你应该扩展原生API吗?作为一个经验法则没有。不幸的是答案更复杂。如果您正在编写像Ember或Angular这样的大型框架,那么这样做可能是个好主意,因为如果API更方便,您的消费者将拥有Benifits。但如果你只是为自己做这件事,那么经验法则是否定的。

理由是这样做会破坏该对象的信任。换句话说,通过添加,更改,修改本机对象,它不再遵循其他任何人(包括您未来的自己)所期望的良好理解和记录的行为。

这种风格隐藏了可以忽视的实现。 这个新方法是什么?这是一个秘密的浏览器吗?它做了什么?我发现了一个错误现在报告给谷歌或微软?。有点夸张但重点是API的真实性现在已经改变,并且在这种情况下出乎意料。它使得可维护性需要额外的思考和理解,如果你只是使用自己的函数或包装器对象就不会这样。它也使得改变更加困难。

相关帖子:Extending builtin natives. Evil or not?

不要试图捣毁其他人(或标准)代码,而只是使用自己的代码。

function toggleAttribute(el, attribute, value) {
  var _value = (value == null ? true : value;
  if (el.hasAttribute(attribute)) {
    el.removeAttribute(attribute);
  } else {
    el.addAttribute(attribute, _value);
  }
};

现在它是安全,可组合,便携和可维护的。再加上其他开发人员(包括你未来的自我)在任何标准或JS API中都没有记录的神奇方法来源时,不会感到困惑。

答案 1 :(得分:1)

请勿修改您不拥有的对象。

想象一下未来的标准定义Element.prototype.toggleAttribute。在分配函数之前,您的代码会检查它是否具有真值。因此,您最终可能会遇到未来的本机功能,其功能可能与您预期的不同。

更重要的是,只需阅读Element.prototype.toggleAttribute就可以调用getter,这可能会运行一些具有不良横向效果的代码。例如,看看获得Element.prototype.id时会发生什么。

您可以跳过检查并直接分配您的功能。但这可能会产生一个限制器,会产生一些不良的横向效应,而且你的功能也不会被指定为属性。

您可以使用属性定义而不是属性赋值。这应该更安全......除非Element.prototype有一些特殊的[[DefineOwnProperty]]内部方法(例如是代理)。

它可能在很多方面失败。不要这样做。

答案 2 :(得分:0)

在我的评估中:没有

大量覆盖Element.prototype会降低性能并可能与标准化冲突,但技术原因并不存在。

答案 3 :(得分:0)

我正在使用几种Element.prototype自定义方法。 到目前为止,一切都很好,直到我观察到奇怪的行为为止。

<!DOCTYPE html >
<html >
<body>
<script>
function doThis( ){
    alert('window');
}
HTMLElement.prototype.doThis = function(  ){
    alert('HTMLElement.prototype');
}
</script>
<button onclick="doThis( )" >Do this</button>
</body>
</html>

单击按钮时,将执行原型方法,而不是全局方法。 浏览器似乎认为this.doThis()很奇怪。为了克服这个问题,我必须在onclick中使用window.doThis()。

如果w3c可以带有diff语法来调用本地/自定义方法,则可能会更好。

myElem.toggleAttribute() // call native method
myElem->toggleAttribute() // call custom method

答案 4 :(得分:-1)

  

是否有任何技术原因不扩展Element原型。

绝对没有!

请原谅我: 绝对没有!

另外 直到昨天,.__proto__实际上是一个非法的原型扩展。 - 今天,这是一个标准。

p.s。:你应该避免使用if(!Element.prototype.toggleAttribute)语法,if(Element.prototype中的“toggleAttribute”)会这样做。