简体   繁体   English

扩展Object.prototype JavaScript

[英]Extending Object.prototype JavaScript

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) . 几乎每个人都认为这是邪恶的,因为它混淆了for(var i in obj)

The Real Question 真正的问题

Ignoring 忽略

  • Incompetent browsers(browsers that don't support Object.defineProperty ) 不称职的浏览器(不支持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(){ /* Makes breakfast, solves world peace, takes out trash */ },
  writable: true,
  configurable: true,
  enumerable: false
});

If you believe the above is unethical, why would they even implement the feature in the first place? 如果你认为上述内容是不道德的,为什么他们甚至会首先实现这个功能呢?

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. 只要你像一个好的开发人员一样使用hasOwnProperty()就可以了。 Worst case, you overload that property elsewhere and lose the method. 最糟糕的情况是,您在其他地方重载该属性并丢失该方法。 But that's your own fault if you do that. 但如果你这样做,这是你自己的错。

I'd say this is almost as evil as before. 我会说这几乎和以前一样邪恶。 The biggest problem, still the same as before, is that Object.prototype is global . 最大的问题,仍然和以前一样,是Object.prototype是全局的 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. 新版本的Javascript具有许多与属性相关的功能,例如将属性定义为可枚举/不可枚举,具有getter和setter ... Object.defineProperty存在是为了控制它。

From Mozilla Docs : 来自Mozilla Docs

This method allows precise addition to or modification of a property on an object. 该方法允许精确地添加或修改对象上的属性。 Normal property addition through assignment creates properties which show up during property enumeration (for...in loop), whose values may be changed, and which may be deleted. 通过赋值添加的正常属性会创建在属性枚举期间显示的属性(对于... in循环),其值可能会更改,并且可能会被删除。 This method allows these extra details to be changed from their defaults. 此方法允许从默认值更改这些额外的详细信息。


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. 能够修改Object.prototype只是它的一个副作用,它也是一个“正常”的对象,就像以前一样邪恶。

.hasOwnProperty() will exclude iteration through inherited properties, which I personally find is often more annoying than helpful. .hasOwnProperty()将通过继承属性排除迭代,我个人发现这通常比有用更烦人。 It largely defeats the usefulness of Object.create() —which is ironic since the same guy who convinced everyone to do .hasOwnProperty() also promoted Object.create() . 它在很大程度上打败了Object.create()的实用性 - 这是具有讽刺意味的,因为同一个人说服每个人做.hasOwnProperty()也提升了Object.create()

Object.prototype should not be extended, for the reasons listed here. 由于此处列出的原因,不应扩展Object.prototype。 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. 我意识到这种情况在所有已发布的最佳实践中.hasOwnProperty() ,但我们真的应该停止对对象密钥迭代“强制” .hasOwnProperty()并拥抱直接对象到对象继承的有用性。

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. 那么在“JavaScript:好的部分”中,有一个类似的功能,我认为这对于改进javascript基础对象(如String,Date等)非常有用,但仅仅是为了这个。

// Add a method conditionally. from "JavaScript: the good parts"

Function.prototype.method = function (name, func) {
    if (!this.prototype[name]) {
        this.prototype[name] = func;
    }
}

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 using hasOwnProperty anyway. 1.在迭代对象时使用hasOwnProperty ,但这并不是一个预防措施,当迭代对象时,我已经在使用hasOwnProperty了。
2. check if the name in Object.prototype.name has existed, this is very safe to avoid name collision. 2.检查Object.prototype.namename是否存在,这样可以避免名称冲突。
3. take advantage of Object.defineProperty() , just add extra safeguard layer. 3.利用Object.defineProperty() ,只需添加额外的安全保护层。

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. 1.方法链接,这只会使代码更具可读性,简洁性,并使编码更加愉快。 In turn makes you happier, and your life easier. 反过来让你更快乐,让你的生活更轻松。
2. solves the browser compatibility issue, you are doing polyfill anyway. 2.解决了浏览器兼容性问题,无论如何你正在进行polyfill。

PS: PS:
Don't do it when working with a large team for sure. 在与大型团队合作时,请不要这样做。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM