为啥 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 始终围绕对对象本身进行操作;
这是不正确的。例如。 JSON
和 Math
总是有自己的方法。没有人会做这样的事情:
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.defineProperty
和 Object.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 中?的主要内容,如果未能解决你的问题,请参考以下文章