gpt4 book ai didi

javascript - Object.prototype 被禁止?

转载 作者:行者123 更新时间:2023-12-03 06:58:53 26 4
gpt4 key购买 nike

回顾:

好吧,自从我问这个问题以来已经有一段时间了。像往常一样,我还是去增强了 Object.prototype ,尽管这里和网络上其他地方都给出了反对它的所有有效论据。我想我就是那种顽固的 SCSS 。

我试图想出一种决定性的方法来防止新方法破坏任何预期的行为,事实证明这是一件非常困难但信息丰富的事情。
我学到了很多关于 JavaScript 的知识。至少我不会尝试任何像扰乱 native 原型(prototype)这样鲁莽的事情(除了 IE < 9 的 String.prototype.trim)。

在这种特殊情况下,我不使用任何库,因此冲突不是我主要关心的问题。但是,在对使用 native 原型(prototype)时可能出现的问题进行了更深入的研究后,我不太可能尝试将此代码与任何库结合使用。

通过研究这种原型(prototype)方法,我对模型本身有了更好的理解。我将原型(prototype)视为某种形式的灵活的传统抽象类,这使我坚持传统的 OOP 思维。这种观点并没有真正公正地对待原型(prototype)模型。道格拉斯·克罗克福德(Douglas Crockford)写了关于这个陷阱的文章,遗憾的是粉红色的背景使我无法阅读全文。

我决定更新这个问题,以防阅读本文的人想亲自看看。我只能说:无论如何,一定要做。我希望你在决定放弃这个相当愚蠢的想法之前,能像我一样学到一些巧妙的东西。一个简单的函数可能同样有效,甚至更好,尤其是在这种情况下。毕竟,它的真正美妙之处在于,只需添加 3 行代码,您就可以使用相同的函数来增强特定对象的原型(prototype)。

<小时/>

我知道我要问一个已经存在很长一段时间的问题,但是:为什么 Object.prototype 被认为是禁区?它就在那里,并且可以像任何其他原型(prototype)一样进行增强。那么,为什么你不应该利用这一点呢?在我看来,只要您知道自己在做什么,就没有理由避开对象原型(prototype)。
以此方法为例:

if (!Object.prototype.getProperties)
{
Object.prototype.getProperties = function(f)
{
"use strict";
var i,ret;
f = f || false;
ret = [];
for (i in this)
{
if (this.hasOwnProperty(i))
{
if (f === false && typeof this[i] === 'function')
{
continue;
}
ret.push(i);
}
}
return ret;
};
}

基本上,它与旧的 for...in 循环相同,您可以在函数中保持安全,或者一遍又一遍地编写。我知道它将被添加到所有对象中,并且由于JavaScript中几乎每个继承链都可以追溯到Object.prototype,但在我的脚本中,我认为它两害相权取其轻。

也许,有人可以比 this chap 更好地告诉我哪里错了。等。
在寻找人们触摸对象原型(prototype)的原因时,一件事不断出现:它打破了for..in 循环事物,但话又说回来:许多框架也是如此,更不用说您自己的继承链了。因此,在我看来,在循环对象的属性时不包含 .hasOwnProperty 检查是不好的做法。

我还发现了this相当有趣。再说一次:有一个评论是相当明确的:扩展原生原型(prototype)是一种不好的做法,但如果 V8 的人这样做了,我有什么资格说他们错了呢?
我知道,这个论点不太成立。

重点是:我真的看不出上面的代码有什么问题。我喜欢它,经常使用它,到目前为止,它从未让我失望过。我什至正在考虑向对象原型(prototype)附加更多函数。除非有人能告诉我为什么我不应该这么做。

最佳答案

事实是,只要您知道自己在做什么以及成本是多少,就可以了。但这是一个很大的“如果”。一些成本示例:

  • 您需要对您选择在增强 Object.prototype 的环境中使用的任何库进行广泛测试。 ,因为压倒性的约定是空白对象没有可枚举的属性。通过将可枚举属性添加到 Object.prototype ,你使该约定变得错误。例如,这很常见:

    var obj = {"a": 1, "b": 2};
    var name;
    for (name in obj) {
    console.log(name);
    }

    ...压倒性的约定是仅显示“a”和“b”,而不显示“getProperties”。

  • 任何编写代码的人都必须接受这样的教育:没有遵守该约定(上述)。

您可以使用 Object.defineProperty 来缓解上述问题(和类似的)如果支持的话,但要注意,即使在 2014 年,像 IE8 这样的浏览器 don't support it正确地保持重要使用(尽管我们希望 XP 正式停产后这种情况会很快改变)。那是因为使用 Object.defineProperty ,您可以添加不可枚举属性(那些不会出现在 for-in 循环中的属性),这样您就会少很多麻烦(此时,您主要担心名称冲突)——但它仅适用于正确实现 Object.defineProperty 的系统(并且正确的实现不能被“填充”)。

在您的示例中,我不会添加 getPropertiesObject.prototype ;我会将其添加到 Object并接受该对象作为参数,就像 ES5 对 getPrototypeOf 所做的那样和类似的。

请注意,Prototype 库因扩展 Array.prototype 而受到很多批评。因为这会影响 for..in循环。这只是 Array s (无论如何你都不应该使用 for..in (除非你使用 hasOwnProperty 保护并且很可能也使用 String(Number(name)) === name )。

...if the V8 people do it, who am I to say they're wrong?

在 V8 上,您可以信赖 Object.defineProperty ,因为 V8 是一个完全兼容 ES5 的引擎。

请注意,即使属性是不可枚举的,也存在问题。多年前,Prototype(间接)定义了 filter功能于 Array.prototype 。它执行您所期望的操作:调用迭代器函数并根据函数选择的元素创建一个新数组。然后 ECMAScript5 出现并定义了 Array.prototype.filter做同样的事情。但有一个问题:很多都是同样的事情。特别是,被调用的迭代器函数的签名是不同的(ECMAScript5 包含一个 Prototype 没有的参数)。情况可能比这更糟糕(我怀疑 - 但无法证明 - TC39 知道 Prototype 并故意避免与它发生太多冲突)。

所以:如果您打算这样做,请注意风险和成本。由于尝试使用现成的库,您可能会遇到丑陋的边缘情况错误,这确实会浪费您的时间......

关于javascript - Object.prototype 被禁止?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10757455/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com