是否也应该避免通过符号扩展内置 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; 

由于symbolstring(原始、不可变)和object(身份)的混合体,因此根据定义,对象属性命名不会发生冲突。

普通对象反射不受符号影响:

Object.getOwnPropertyNames(Array.prototype).indexOf("empty"); // -1

但是Reflect.ownKeys(Array.prototype) 的 ES2015 反射是。

所以这个问题主要是关于我们将来如何使用Reflect.ownKeysObject.getOwnPropertySymbols

【问题讨论】:

别忘了你现在可以继承内置函数,所以还有一个理由不扩展内置函数的原型 @RGraham 我问这个问题的主要原因是为了更好地理解符号的用例或边缘情况,因为它们是一个相对较新的功能。我想我实际上不会扩展内置的原型。 【参考方案1】:

是的。

“不要修改你不拥有的东西”规则有两个部分:

    您可能会导致名称冲突,并且可能会破坏他们的代码。

    通过触摸不属于您的东西,您可能会不小心覆盖某些其他库使用的东西。这会以意想不到的方式破坏他们的代码。

    您可以创建紧密的依赖关系,并且它们可以破坏您的代码。

    通过将您的代码如此紧密地绑定到某个其他对象,如果它们进行了一些重大更改(例如删除或重命名类),您的代码可能会突然中断。

使用符号可以避免#1,但你仍然会遇到#2。通常不鼓励此类类之间的紧密依赖关系。如果其他类曾经是frozen,您的代码仍然会中断。 this question 上的 answers 仍然适用,只是原因略有不同。

您希望专注于 loosely binding 您的依赖项,以支持更好的测试(松散绑定更容易模拟)和更容易维护(一些明显的连接更容易记录和更新)。

明确一点:名称冲突只是紧密依赖关系引起的问题的症状。

【讨论】:

@IvenMarquardt ES6 还是经典原型,影响是一样的。您正在创建对没有合同的事物的双向依赖。使用String.prototype.substr 是一种安全的单向依赖:您使用该函数,它们提供了一份合同,说明它将存在以及它的行为方式。向String.prototype 注入一些东西更加迂回(你既可以修改也可以使用它们),而且他们通常不会提供合同说这仍然是可能的。 最后,这归结为“这可能很危险,不要碰它。”虽然这会让现实生活变得无聊,但它会让代码稳定 但是如果你创建一个 Array.prototype 的实例然后让它不可变(冻结),pushpop 等也会被破坏。能再举一个具体的例子吗? @IvenMarquardt 不冻结实例,冻结类。他们还可以删除一个类,重命名它,要求它被导入,或者任何其他改变可见性的东西。任何意外更改都有可能破坏您的代码。 虽然我将您的示例视为过于笼统且不太可能(至少在 Javascript 的上下文中),但我明白您的观点。谢谢!

以上是关于是否也应该避免通过符号扩展内置 Javascript 原型?的主要内容,如果未能解决你的问题,请参考以下文章

是否应该避免嵌套锁定请求?

初学者要注意这8个web前端javascrip陷阱

UICollectionView 中的高内存使用 [重复]

JavaScrip 全选/取消/反选

是否应该避免使用 LINQ,因为它很慢? [关闭]

JavaScrip:Function