是否也应该避免通过符号扩展内置 Javascript 原型?
Posted
技术标签:
【中文标题】是否也应该避免通过符号扩展内置 Javascript 原型?【英文标题】:Should the extension of built-in Javascript prototypes through symbols also be avoided? 【发布时间】:2016-04-17 10:06:12 【问题描述】:这是predominant opinion,内置的 javascript 原型不应该被扩展(或以任何方式改变):
Array.prototype.empty = function () return this.length === 0; // don't try that
此规则是否也适用于 ES2015 符号?
const empty = Symbol("empty");
Array.prototype[empty] = function empty() return this.length === 0;
由于symbol
是string
(原始、不可变)和object
(身份)的混合体,因此根据定义,对象属性命名不会发生冲突。
普通对象反射不受符号影响:
Object.getOwnPropertyNames(Array.prototype).indexOf("empty"); // -1
但是Reflect.ownKeys(Array.prototype)
的 ES2015 反射是。
所以这个问题主要是关于我们将来如何使用Reflect.ownKeys
和Object.getOwnPropertySymbols
。
【问题讨论】:
别忘了你现在可以继承内置函数,所以还有一个理由不扩展内置函数的原型 @RGraham 我问这个问题的主要原因是为了更好地理解符号的用例或边缘情况,因为它们是一个相对较新的功能。我想我实际上不会扩展内置的原型。 【参考方案1】:是的。
“不要修改你不拥有的东西”规则有两个部分:
您可能会导致名称冲突,并且您可能会破坏他们的代码。
通过触摸不属于您的东西,您可能会不小心覆盖某些其他库使用的东西。这会以意想不到的方式破坏他们的代码。
您可以创建紧密的依赖关系,并且它们可以破坏您的代码。
通过将您的代码如此紧密地绑定到某个其他对象,如果它们进行了一些重大更改(例如删除或重命名类),您的代码可能会突然中断。
使用符号可以避免#1,但你仍然会遇到#2。通常不鼓励此类类之间的紧密依赖关系。如果其他类曾经是frozen,您的代码仍然会中断。 this question 上的 answers 仍然适用,只是原因略有不同。
您希望专注于 loosely binding 您的依赖项,以支持更好的测试(松散绑定更容易模拟)和更容易维护(一些明显的连接更容易记录和更新)。
明确一点:名称冲突只是紧密依赖关系引起的问题的症状。
【讨论】:
@IvenMarquardt ES6 还是经典原型,影响是一样的。您正在创建对没有合同的事物的双向依赖。使用String.prototype.substr
是一种安全的单向依赖:您使用该函数,它们提供了一份合同,说明它将存在以及它的行为方式。向String.prototype
注入一些东西更加迂回(你既可以修改也可以使用它们),而且他们通常不会提供合同说这仍然是可能的。
最后,这归结为“这可能很危险,不要碰它。”虽然这会让现实生活变得无聊,但它会让代码稳定。
但是如果你创建一个 Array.prototype 的实例然后让它不可变(冻结),push
和 pop
等也会被破坏。能再举一个具体的例子吗?
@IvenMarquardt 不冻结实例,冻结类。他们还可以删除一个类,重命名它,要求它被导入,或者任何其他改变可见性的东西。任何意外更改都有可能破坏您的代码。
虽然我将您的示例视为过于笼统且不太可能(至少在 Javascript 的上下文中),但我明白您的观点。谢谢!以上是关于是否也应该避免通过符号扩展内置 Javascript 原型?的主要内容,如果未能解决你的问题,请参考以下文章