我偶尔会看到一些评论,说修改JavaScript对象的原型是不被赞同的行为?个人认为这并不会成为一个问题。例如扩展Array对象以具有map和include方法或创建更强大的Date方法。
我偶尔会看到一些评论,说修改JavaScript对象的原型是不被赞同的行为?个人认为这并不会成为一个问题。例如扩展Array对象以具有map和include方法或创建更强大的Date方法。
问题在于原型可以在多个地方进行修改。例如,一个库将向数组的原型中添加map方法,而您自己的代码将添加相同的方法,但目的不同。因此,一个实现将会被破坏。
document.getElementsByTagName('p').map(function () { ... });
因为它是一个NodeList,而不是一个Array。上面的代码会导致类似以下的错误:Uncaught TypeError: [object NodeList] doesn't have method 'map'
。
我应该指出,有非常简单的方法可以将NodeList和其他类数组对象转换为真正的数组。
创建一个全新的全局变量并在其上堆积实用程序。jQuery和Dojo都采用此方法。
优点:
缺点:
使用这种方法,您仍然无法做到..
document.getElementsByTagName('p').map(function () { ... });
..但你可以做到..
jQuery.map(document.getElementsByTagName('p'), function () { ... });
但是正如 Matt 指出的那样,在通常情况下,您会使用上述方法来执行操作。
jQuery('p').map(function () { ... });
最终,这取决于你。如果你可以接受被覆盖或覆盖他人的风险,那么我强烈推荐原型设计。它是我喜欢的样式,我认为风险值得结果。如果你对此不像我那么确定,那么收集也是一种很好的样式。它们都有优缺点,但总的来说,它们通常会产生相同的最终结果。
Object.prototype
的扩展可能不可用? - KooiIncObject.prototype
扩展,毕竟这是OP问题的主题。'Object.prototype.hey = 'hey'; alert('hi'.hey);' 将会警报'hey',(213).hey
、new SomeHomeBrewObject().hey
、[].hey
等也是如此。顺便说一下,这可能是避免过多Object.prototype
增强的另一个相当有效的论据。 - KooiInc正如bjornd指出的那样,猴子补丁只在涉及多个库时才是问题。因此,如果您正在编写可重用的库,则不建议这样做。然而,在使用javascript中的主机对象时消除跨浏览器兼容性问题仍然是目前最好的技术。
请参见2009年的这篇博客文章(或Wayback Machine原始网页), 一个真实的事件说明了当prototype.js和json2.js一起使用时会发生什么。
有一篇来自Nicholas C. Zakas的优秀文章,解释了为什么这种做法不应该出现在任何团队或客户项目中的程序员心中(也许可以对教育目的进行一些调整,但不适用于普通项目)。
可维护的JavaScript:不要修改您不拥有的对象: https://www.nczonline.net/blog/2010/03/02/maintainable-javascript-dont-modify-objects-you-down-own/
例如,目前有一个关于String.prototype.replaceAll的提案。如果您发布了一个广泛使用的库,并且该库monkeypatches一个自定义的非标准方法到这正是
Array.prototype.flatten
和Array.prototype.contains
发生的情况。简而言之,为这些方法编写了规范,它们的提议到达了阶段3,然后浏览器开始发布它们。但是,在两种情况下,发现有古老的库用自己的方法与新方法相同的名称修补了内置的Array
对象,并具有不同的行为;结果,网站崩溃,浏览器不得不退出实现新方法,规范也必须进行编辑。(方法被重命名。)
String.prototype.replaceAll
,则replaceAll
名称将不再可供规范编写者使用;在浏览器可以实现它之前,必须更改它。