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

IT技术 javascript ecmascript-5 consistency
2021-01-16 10:10:50

ES5添加数量方法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
});

任何人都可以冷却我的好奇心,为什么会这样?是否有任何代码片段会破坏?标准委员会是否就他们选择这种方法的原因进行了任何公开讨论?

2个回答

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

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

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

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

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

[...]

以下是一些被认为导致选定设计的替代方案。

显而易见的初始想法,遵循已经存在的标准方法 Object.prototype.propertyIsEnumerable 的示例,是在 Object.prototype 上为其他属性添加额外的“propertyIs...”查询方法和一组并行的属性更改方法。

[...]

当我们考虑这种方法时,有很多我们不喜欢的地方,这似乎与上述 API 设计指南相悖:

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

[...]

Crockford 直接参与了 ES5 的设计,最初提出了“beget”。在随后的设计讨论中,“create”成为首选名称。他在他的书中重新命名了“beget”以反映 ES 的设计决策。
2021-03-14 10:10:50
有趣……你知道这是如何排列的Object.create吗?克罗克福德是Object.create在做出这些决定之后还是之前提出的?
2021-03-16 10:10:50
好问题。我不知道:)我认为克罗克福德改名他Object.begetObject.create约当这些API被讨论的同一时间。FWIW,该文档说:“请注意,没有可选第二个参数的 Object.create 与广泛推广的 beget 函数本质上是相同的操作。我们(也许并不奇怪)同意这个函数的效用,但认为“beget”这个词可能会让许多非英语母语者感到困惑。
2021-03-16 10:10:50
我在这里找到了那个文件,@OliverSieweke
2021-03-21 10:10:50
感谢您提供此类相关资源的链接!
2021-03-30 10:10:50

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

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

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

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

...这是因为这些属性(.constructor.hasOwnProperty等)本身与“枚举”属性设置为false定义。从 ES5 开始,我们还可以创建自己的属性,这些属性不会出现在for in循环中(使用Object.definePropertyandObject.create的第二个参数)
2021-03-30 10:10:50
我也错了“没有人做”。在原型中,他们toJSON用于数组,这JSON.stringify([])在 Prototype 1.6 中中断
2021-04-06 10:10:50
我同意你的观点Math……但是Object.prototype作为客户端扩展和作为语言本身扩展之间的区别是完全不同的;语言的扩展不会出现在 中for ( in ),而客户端扩展会出现:jsfiddle.net/mDfCe/1
2021-04-10 10:10:50