他的推理非常糟糕。它(和Object.getOwnPropertyNames
)不是为了使用 Caja 和类似而简单添加的。Caja 也不会简单地删除它们!Caja 拦截Object.getOwnPropertyNames
以实现WeakMap
(我的 shim也是如此),据我所知,它不会修改 getPrototypeOf。实际上,无论如何它都是毫无意义的,因为Object.getPrototypeOf(o)
它与在除 IE 之外的每个浏览器中实现的相同,o.__proto__
并且不能(当前)关闭。这意味着唯一可以删除的浏览器Object.getPrototypeOf
是 IE9 和 IE10。
我认为他会给出的原因是其中一些功能主要是供“图书馆作者”类型使用的。这是参与规范过程的人通常相信/说过的话,我相信这是一个合法的主张;属性描述符/属性和其他“元”级 API 是更高级的功能,使用起来很麻烦,通常需要更完整的语言掌握才能正确使用。但是,这仍然不等于“不要使用它们”的一揽子建议。不过,这个更准确的说法甚至不是他提出的论点。
关于视频的一个额外说明,他在其中做了不正确的陈述。他说属性属性(可枚举、可配置、可写)一旦设置就不可更改。这是不正确的。只要configurable
是真的,这些都可以改变。一旦设置为 false,属性就会被冻结(属性也不能删除)。
编辑:在完成研究之后,我发现了一些关于这个特性和其他对象函数的原始讨论。我理解的总结如下。
人们担心能够访问对象的 [[Prototype]] 会带来安全隐患。然而,这些问题通过 Object.freeze 之类的东西得到了更全面和适当的解决,并且部分解决了(也是一个原因)这些函数作为静态函数(可在一个位置删除)而不是 Object.prototype 或神奇地存在于 Object 上在历史上像proto这样的每个对象上。
提出的另一个问题是破坏封装
确实,proto或 getPrototypeOf 打破了对象的封装障碍,并揭示了可能打算隐藏的实现细节。提议的 getProperty 函数也是如此,除其他外,它使观察者可以访问实现 getter/setter 属性的函数。一般来说,这就是反射的本质。-Allen Wirfs-Brock
从实现端提出的一个问题是关于暴露实现细节(主要是源于 DOM 如何工作的问题,此后通过更改 DOM 对多重继承的使用和向 WebIDL 的过渡解决了这一问题)。
另一方面,提供对对象原型的反射访问对兼容性有害,因为它会阻止实现在不破坏网络的情况下引入中间原型。考虑只有 Numbers 的例子,然后兼容地引入更具体的 Numbers 子类。——瓦尔德玛·霍瓦特
这个问题也与脚本协调邮件列表中提到的另一个问题有关,即内部隐藏原型是相同的跨框架。这个问题也是 ES5(和 IE8)的历史,它决定并实现每个框架必须实例化自己的一组 DOM 原型。因此,到 ES5 正式发布时,由于这个原因隐藏原型不再相关。
我看到的共识不符合 Crockford 的解释。大多数情况下,这似乎只是他自己观点的重申。
总之,不提供对对象原型的反射访问并不能真正提供任何真正的安全性,它只会使一些有用的任务不那么方便。
-Allen Wirfs-Brock
总的来说,我同意你的看法,很高兴听到反射不是“真正的安全”的敌人。
——布伦丹·艾希
这方面的出发点是提议的 ECMAScript 3.1 静态对象函数:用例和基本原理(由 Crockford 和其他人在 TC39 上编写)。后续,我从中引用,是这个 es-discuss 线程。特别是这篇文章和这篇文章。