Object.prototype是Verboten吗? [英] Object.prototype is Verboten?

查看:47
本文介绍了Object.prototype是Verboten吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

重获:

好,距离我问这个问题已经有一段时间了.和往常一样,尽管这里和网络上其他地方都给出了反对它的所有有效论据,但我还是继续增加了 Object.prototype .我想我只是那种固执的混蛋.

Ok, it's been a while since I asked this question. As usual, I went and augmented the Object.prototype anyway, in spite of all the valid arguments against it given both here and elsewhere on the web. I guess I'm just that kind of stubborn jerk.

我试图提出一种确定性的方法,以防止新方法破坏任何预期的行为,事实证明这是一件非常艰巨的事情,但可以提供很多信息.
我已经学到了很多关于JavaScript的知识.至少我不会尝试像打乱本机原型一样粗鲁的尝试(IE 9的 String.prototype.trim 除外).

I've tried to come up with a conclusive way of preventing the new method from mucking up any expected behaviour, which proved to be a very tough, but informative thing to do.
I've learned a great many things about JavaScript. Not in the least that I won't be trying anything as brash as messing with the native prototypes, (except for String.prototype.trim for IE < 9).

在这种情况下,我不使用任何库,因此冲突不是我的主要关注点.但是,在研究本机原型时可能会遇到更多的麻烦,因此我不太可能将此代码与任何lib结合使用.

In this particular case, I don't use any libs, so conflicts were not my main concern. But having dug a little deeper into possible mishaps when playing around with native prototypes, I'm not likely to try this code in combination with any lib.

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

By looking into this prototype approach, I've come to a better understanding of the model itself. I was treating prototypes as some form of flexible traditional abstract class, making me cling on to traditional OOP thinking. This viewpoint doesn't really do the prototype model justice. Douglas Crockford wrote about this pitfall, sadly the pink background kept me from reading the full article.

我已决定更新此问题,以免偶然阅读此书的人看到他们自己.我只能说:一定要做.我希望您像我一样学到一些整洁的东西,然后再决定放弃这个相当愚蠢的想法.一个简单的功能可能同样有效,甚至更好,特别是在这种情况下.毕竟,它的真正优点在于,只需添加三行代码,就可以使用该功能完全相同,从而完全扩展特定对象的原型.

I've decided to update this question in the off chance people who read this are tempted to see for themselves. All I can say to that is: by all means, do. I hope you learn a couple of neat things, as I did, before deciding to abandon this rather silly idea. A simple function might work just as well, or better even, especially in this case. After all, the real beauty of it is, that by adding just 3 lines of code, you can use that very same function to augment specific objects' prototypes all the same.

我知道我要问一个已经存在了很长时间的问题,但是:为什么Object.prototype被认为是限制?它在那里,并且可以像其他任何原型一样全部增强.那么,为什么不应该利用这个优势呢?在我看来,只要您知道自己在做什么,就没有理由避免使用Object原型.
以这种方法为例:

I know I'm about to ask a question that has been around for quite a while, but: Why is Object.prototype considered to be off limits? It's there, and it can be augmented all the same, like any other prototype. Why, then, shouldn't you take advantage of this. To my mind, as long as you know what you're doing, there's no reason to steer clear of the Object prototype.
Take this method for example:

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 ,但是在我的脚本中,我认为两种弊端中的较小者.

Basically, it's the same old for...in loop you would either keep safe in a function, or write over and over again. I know it will be added to all objects, and since nearly every inheritance chain in JavaScript can be traced back to the Object.prototype, but in my script, I consider it the lesser of two evils.

也许,比起

Perhaps, someone could do a better job at telling me where I'm wrong than this chap, among others.
Whilst looking for reasons people gave NOT to touch the Object's prototype, one thing kept cropping up: it breaks the for..in loop-thingy, but then again: many frameworks do, too, not to mention your own inheritance chains. It is therefore bad practice not to include a .hasOwnProperty check when looping through an object's properties, to my mind.

我还发现

I also found this rather interesting. Again: one comment is quite unequivocal: extending native prototypes is bad practice, but if the V8 people do it, who am I to say they're wrong?
I know, that argument doesn't quite stack up.

重点是:我看不到上面的代码有问题.我喜欢它,经常使用它,到目前为止,它从未让我失望过.我什至在考虑将更多的功能附加到对象原型.除非有人能告诉我为什么不这样做,否则就是这样.

The point is: I can't really see a problem with the above code. I like it, use it a lot and so far, it hasn't let me down once. I'm even thinking of attaching a couple more functions to the Object prototype. Unless somebody can tell me why I shouldn't, that is.

推荐答案

事实是,只要您知道自己在做什么和花费多少,就可以了.但这是一个"if".费用示例:

The fact is, it's fine as long as you know what you're doing and what the costs are. But it's a big "if". Some examples of the costs:

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

  • You'll need to do extensive testing with any library you choose to use with an environment that augments Object.prototype, because the overwhelming convention is that a blank object will have no enumerable properties. By adding an enumerable property to Object.prototype, you're making that convention false. E.g., this is quite common:

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

...以 压倒性的 约定,只有"a"和"b"出现,而不是"getProperties".

...with the overwhelming convention being that only "a" and "b" will show up, not "getProperties".

任何从事该代码工作的人都必须接受以下事实的教育:

Anyone working on the code will have to be schooled in the fact that that convention (above) is not being followed.

如果受支持,则可以使用 Object.defineProperty (及类似方法)缓解上述问题,但要注意,即使在2014年,像IE8这样的浏览器也会 Object.defineProperty ,您可以添加不可枚举属性(那些不会出现在 for-in 循环中的属性),并且因此您的麻烦会减少很多(那时,您主要担心名称冲突)–—但它仅适用于正确实现 Object.defineProperty 的系统(并且不能填充"正确的实现).

You can mitigate the above by using Object.defineProperty (and similar) if supported, but beware that even in 2014, browsers like IE8 that don't support it properly remain in significant use (though we can hope that will change quickly now that XP is officially EOL'd). That's because using Object.defineProperty, you can add non-enumerable properties (ones that don't show up in for-in loops) and so you'll have a lot less trouble (at that point, you're primarily worried about name conflicts) — but it only works on systems that correctly implement Object.defineProperty (and a correct implementation cannot be "shimmed").

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

In your example, I wouldn't add getProperties to Object.prototype; I'd add it to Object and accept the object as an argument, like ES5 does for getPrototypeOf and similar.

请注意,原型库在扩展 Array.prototype 时会遇到很多麻烦,因为这会影响 for..in 循环.那只是 Array s(无论如何,您都不应使用 for..in (除非您使用了 hasOwnProperty 防护,可能也是 String(Number(name))=== name ).

Be aware that the Prototype library gets a lot of flak for extending Array.prototype because of how that affects for..in loops. And that's just Arrays (which you shouldn't use for..in on anyway (unless you're using the hasOwnProperty guard and quite probably String(Number(name)) === name as well).

...如果V8人员这样做,我是谁,他们错了吗?

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

在V8上,您可以依赖 Object.defineProperty ,因为V8是完全符合ES5的引擎.

On V8, you can rely on Object.defineProperty, because V8 is an entirely ES5-compliant engine.

请注意,即使属性不可枚举,也存在问题.多年前,Prototype(间接)在 Array.prototype 上定义了一个 filter 函数.它可以满足您的期望:调用迭代器函数,并根据该函数选择的元素创建一个新数组.然后ECMAScript5出现了,并定义了 Array.prototype.filter 来做同样的事情.但是有一个问题: 很多 是同一件事.特别是,被调用的迭代器函数的签名是不同的(ECMAScript5包含Prototype没有提供的参数).它本来可以比这更糟(我怀疑,但不能证明TC39知道原型,并有意避免与其产生太多冲突).

Note that even when the properties are non-enumerable, there are issues. Years ago, Prototype (indirectly) defined a filter function on Array.prototype. And it does what you'd expect: Calls an iterator function and creates a new array based on elements the function chooses. Then ECMAScript5 came along and defined Array.prototype.filter to do much the same thing. But there's the rub: Much the same thing. In particular, the signature of the iterator functions that get called is different (ECMAScript5 includes an argument that Prototype didn't). It could have been much worse than that (and I suspect — but cannot prove — that TC39 were aware of Prototype and intentionally avoided too much conflict with it).

因此:如果您要这样做,请注意风险和成本.尝试使用现成的库可能会遇到的丑陋的,极端的bug确实会浪费您的时间...

So: If you're going to do it, be aware of the risks and costs. The ugly, edge-case bugs you can run into as a result of trying to use off-the-shelf libraries could really cost you time...

这篇关于Object.prototype是Verboten吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆