为啥 ES5 Object 方法没有添加到 Object.prototype 中?

Posted

技术标签:

【中文标题】为啥 ES5 Object 方法没有添加到 Object.prototype 中?【英文标题】:Why were ES5 Object methods not added to Object.prototype?为什么 ES5 Object 方法没有添加到 Object.prototype 中? 【发布时间】:2022-01-02 01:20:53 【问题描述】:

ES5 在methods 中添加了methods 的number 到Object,这似乎打破了javascript 的语义一致性。

例如,在此扩展之前,JavaScript API 始终围绕在对象本身上操作

var arrayLength = [].length;
var firstPosInString = "foo".indexOf("o");

... 就像新的 Object 方法一样;

var obj =  ;
Object.defineProperty(obj, 
    value: 'a',
    writable: false
);

...当以下内容更符合时:

var obj =  ;
obj.defineProperty(
    value: 'a',
    writable: false
);

谁能冷静我的好奇心,为什么会这样?是否有任何代码 sn-ps 这会破坏?标准委员会是否就他们为什么选择这种方法进行了公开讨论?

【问题讨论】:

【参考方案1】:

JavaScript API 始终围绕对对象本身进行操作;

这是不正确的。例如。 JSONMath 总是有自己的方法。没有人会做这样的事情:

var x = 0;
x.cos(); // 1.0
("a":[0,1],"p":"x":3,"y":4).toJSON();

网络上有很多文章说明为什么扩展 Object.prototype 是一件坏事。是的,它们是关于 client 代码的,但是也许这对于某些方面的内置方法也是不利的。

【讨论】:

我同意你关于Math 的观点...但是将Object.prototype 扩展为客户端 和语言本身之间的区别是完全不同的; language 的扩展不会出现在 for ( in ) 中,而 client 扩展会出现:jsfiddle.net/mDfCe/1 ... 这是因为这些属性(.constructor.hasOwnProperty 等)在本机定义时将“可枚举”属性设置为 false。从 ES5 开始,我们还可以创建自己的属性,这些属性不会出现在 for in 循环中(使用 Object.definePropertyObject.create 的第二个参数) 我对“没有人做”也是错误的。在原型中,他们使用toJSON 表示数组,这在原型 1.6 中破坏了 JSON.stringify([])【参考方案2】:

Allen Wirfs-Brock 本人(ES5 规范的编辑,TC39 的成员)在 "Proposed ECMAScript 3.1 Static Object Functions: Use Cases and Rationale" document (pdf) 中很好地解释了这一切。

我建议阅读所有内容。它非常简短,易于理解,并且很好地展示了这些 ES5 新增功能背后的思考过程。

但要引用相关部分(强调我的):

在推出之前考虑了许多替代 API 设计 选择了建议的 API。在考虑替代方案的过程中,我们 制定了一套非正式的指导方针,我们在 考虑替代方案。这些准则是:

干净利落地分离元层和应用层。 尽量减少 API 表面积(即方法的数量及其参数的复杂性)。 关注命名和参数设计的可用性。 尝试重复应用设计的基本元素。 如果可能,允许程序员或实现静态优化 API 的使用。

[...]

以下是一些被认为会导致 选定的设计。

明显的初步想法,遵循已经 现有的标准方法 Object.prototype.propertyIsEnumerable,被 在 Object.prototype 上添加额外的“propertyIs...”查询方法 其他属性和一组并行的属性更改方法。

[...]

当我们考虑这种方法时,有很多关于它的东西 我们不喜欢的,这似乎与上面的 API 设计相反 指导方针:

合并而不是分离元和应用层。作为 Object.prototype 上的方法,方法将成为公共的一部分 程序中每个应用程序对象的接口。因此,他们需要 让每个开发者都能理解,而不仅仅是库设计者。

[...]

【讨论】:

有趣...你知道这与Object.create 是如何匹配的吗? Crockford 是在做出这些决定之后还是在此之前提出的 Object.create 好问题。我不知道 :) 我认为 Crockford 在讨论这些 API 的同时将他的 Object.beget 重命名为 Object.create。 FWIW,文档说:'请注意,没有可选的第二个参数的 Object.create 与被广泛推广的 beget 函数本质上是相同的操作。我们(也许并不奇怪)同意这个函数的实用性,但认为“beget”这个词可能会让许多非英语母语的人感到困惑。' Crockford 直接参与了 ES5 的设计,最初提出了“beget”。在随后的设计讨论中,“create”成为首选名称。他在书中将“beget”重命名为反映 ES 设计决策。 感谢您提供此类相关资源的链接! 我找到了那个文件here,@OliverSieweke

以上是关于为啥 ES5 Object 方法没有添加到 Object.prototype 中?的主要内容,如果未能解决你的问题,请参考以下文章

es5_Object

es5_Object

对象的属性

ES5的常用对象方法详解

为啥 java String类 中的valueOf(Object obj) 空时返回的是"null"而不是null

原型链&Object的一些方法