扩展 Object.prototype JavaScript
我不是在问这是否可以:
Object.prototype.method = function(){};
几乎每个人都认为这是邪恶,因为它搞乱了for(var i in obj)
。
真正的问题
忽略
- 不合格的浏览器(不支持
Object.defineProperty
的浏览器) - 属性冲突或覆盖的可能性
假设您有一些令人难以置信有用的方法,这被认为是错误的/不道德?
Object.defineProperty(Object.prototype, 'methodOnSteriods',{
value: function(){ /* */ },
writable: true,
configurable: true,
enumerable: false
});
如果您认为上述内容是不道德的,那么他们为什么要首先实现该功能呢?
I am not asking if this is okay:
Object.prototype.method = function(){};
This is deemed evil by pretty much everyone, considering it messes up for(var i in obj)
.
The Real Question
Ignoring
- Incompetent browsers(browsers that don't support
Object.defineProperty
) - Potential for property collision or overriding
Assuming you have some incredibly useful method, is this considered wrong/unethical?
Object.defineProperty(Object.prototype, 'methodOnSteriods',{
value: function(){ /* */ },
writable: true,
configurable: true,
enumerable: false
});
If you believe the above is unethical, why would they even implement the feature in the first place?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
2021 年更新
尽管这是公认的答案,但 10 年的经验告诉我这不是最好的主意。几乎任何可以避免污染全局范围的事情都是一件非常非常好的事情。
下面的原始答案,为了后代,并且因为堆栈溢出不会让我删除已接受的答案。
2011 年的原始答案
我认为如果它在你的目标环境中工作就很好。
我还认为原型扩展偏执被夸大了。只要您像优秀的开发人员一样使用
hasOwnProperty()
就可以了。最坏的情况是,您在其他地方重载该属性并丢失该方法。但如果你这样做了,那是你自己的错。UPDATE from 2021
Despite this being the accepted answer, 10 years of experience has taught me this isn't the best idea. Pretty much anything you can do to avoid polluting the global scope is a very very good thing.
Original answer below, for posterity, and because stack overflow will not let me delete an accepted answer.
Original answer from 2011
I think it's fine if it works in your target environment.
Also I think prototype extension paranoia is overblown. As long as you use
hasOwnProperty()
like a good developer that it's all fine. Worst case, you overload that property elsewhere and lose the method. But that's your own fault if you do that.我想说这几乎和以前一样邪恶。最大的问题仍然和以前一样,是Object.prototype 是全局的。虽然你的方法目前可能正在解决世界和平问题,但它可能会覆盖别人的方法(保证银河和平),或者将来可能会被你无法控制的某个库覆盖(因此世界再次陷入混乱)
新版本Javascript 有很多与属性相关的功能,例如定义可枚举/不可枚举的属性、具有 getter 和 setter...Object.defineProperty 的存在就是为了对此进行控制。
来自 Mozilla 文档:
这个新功能基本上需要支持新功能,并且您应该在自己的东西上使用它。能够修改 Object.prototype 只是它作为“普通”对象的副作用,并且和以前一样邪恶。
I'd say this is almost as evil as before. The biggest problem, still the same as before, is that Object.prototype is global. While your method might currently be solving world peace, it might have overwriten someone else's method (that was guaranteeing galactic peace) or may be overwritten in the future by some library you have no control over (therefore plunging the world into chaos again)
New versions of Javascript have lots of features related to properties, such as definig a property to be enumerable/not enumerable, having getters and setters... Object.defineProperty existis to give control over this.
From Mozilla Docs:
This new function is basically required to support the new features and you are supposed to use it on your own stuff. Being able to modify Object.prototype is just a side effect of it also being a "normal" object and is just as evil as before.
在“JavaScript:好的部分”中,有一个类似的函数,我认为这对于改进 javascript 基本对象(如 String、Date 等)非常有用,但仅此而已。
Well in "JavaScript: the good parts", there is a similar function, i think that is very usefull to improve javascript base objects (like String, Date, etc..), but just for that.
.hasOwnProperty()
将排除通过继承属性进行的迭代,我个人认为这通常更烦人而不是有用。它在很大程度上削弱了Object.create()
的实用性——这很讽刺,因为说服每个人都这样做.hasOwnProperty()
的同一个人也推广了Object.create ()
。由于此处列出的原因,不应扩展 Object.prototype。如果您确实想扩展它,请使扩展不可迭代。
我意识到这与所有已发布的最佳实践背道而驰,但我们确实应该停止在对象键迭代上“强制”
.hasOwnProperty()
,并拥抱直接对象到对象的有用性遗产。.hasOwnProperty()
will exclude iteration through inherited properties, which I personally find is often more annoying than helpful. It largely defeats the usefulness ofObject.create()
—which is ironic since the same guy who convinced everyone to do.hasOwnProperty()
also promotedObject.create()
.Object.prototype should not be extended, for the reasons listed here. If you really do want to extend it, then make the extensions non-iterable.
I realize this flies in the face of all of the published best-practices, but we really should stop “mandating”
.hasOwnProperty()
on object key iterations and embrace the usefulness of direct object-to-object inheritance.简短的回答是,是的,你应该这样做。
在此之前,需要采取一些预防措施:
1. 在迭代对象时使用
hasOwnProperty
,但这并不是真正的预防措施,在迭代对象时,我已经在使用hasOwnProperty
了。2. 检查
Object.prototype.name
中的name
是否存在,这样可以非常安全地避免名称冲突。3.利用
Object.defineProperty()
,只需添加额外的保护层即可。正如您所看到的,它并不是很复杂。
一旦您考虑了风险/缺点,现在就会出现优点:
1.方法链接,这只会让代码更可读、更简洁,让编码变得更愉快。反过来,你会更快乐,你的生活也会更轻松。
2.解决浏览器兼容性问题,反正你是在做polyfill。
PS:
与大型团队合作时,绝对不要这样做。
The short answer is Yes, you should do it.
Before doing it, there are several precautions need to take:
1. using
hasOwnProperty
when iterating object, but this isn't really a precautions, when iterating object, I am already usinghasOwnProperty
anyway.2. check if the
name
inObject.prototype.name
has existed, this is very safe to avoid name collision.3. take advantage of
Object.defineProperty()
, just add extra safeguard layer.As you can see, it's not very complicated.
Now comes the advantages once you have taken care of the risks/disadvantages:
1. method chaining, this just makes code more readable, terse, and making coding more enjoyable. In turn makes you happier, and your life easier.
2. solves the browser compatibility issue, you are doing polyfill anyway.
P.S.:
Don't do it when working with a large team for sure.