我已经看到很多关于扩展Element的讨论。据我所知,这些是主要问题:
鉴于一个项目没有引用其他库,文档会发生变化,并且不会给历史浏览器带来任何影响:
是否有技术理由不扩展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:我已经删除了该方法是否已存在的测试。即使这种方法已经存在,覆盖它也更容易预测。在任何情况下,我假设这里的要点是该方法尚未定义,更不用说实现了。这就是重点。
答案 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”)会这样做。