他的推理非常糟糕。它(以及 Object.getOwnPropertyNames
)并不仅仅是为了 Caja 和类似工具而添加的。Caja 也没有简单地删除它们!Caja 拦截 Object.getOwnPropertyNames
以实现 WeakMap
(我的 my shim 也一样),据我所知它并不修改 getPrototypeOf。事实上,这样做是毫无意义的,因为 Object.getPrototypeOf(o)
和 o.__proto__
是相同的,在除 IE 之外的所有浏览器中都已经实现,并且不能(目前)被关闭。这意味着从中删除 Object.getPrototypeOf
只会影响 IE9 和 IE10。
我认为他的原因是其中一些函数主要是为“库作者”类型的用法而设计的。这是规范制定过程中常见的信念/说法,我认为这是一个合理的观点;属性描述符/属性和其他“元”级别的API是更高级的功能,使用起来可能很麻烦,并且通常需要更完整的语言掌握才能正确使用。然而,这仍然不能成为“不要使用它们”的全面建议。尽管如此,他并没有提出这个更准确的观点作为争论的论点。
关于视频的一个额外说明,他说属性属性(可枚举,可配置,可写)一旦设置就无法更改。这是不正确的。只要configurable为true,这些可以更改。一旦设置为false,属性就会被冻结(也不能删除属性)。
编辑:经过调查,我找到了关于这个功能和其他对象函数的原始讨论。据我所知,总结如下。
有人担心能够访问对象的[[Prototype]]会带来安全隐患。然而,通过诸如Object.freeze等方式更充分和适当地解决了这些问题,并且这也部分解决了(并且是一个原因),这些函数作为静态函数存在于Object上(可以在一个位置删除),而不是存在于Object.prototype上或者像proto一样神奇地存在于每个对象上。
另一个提出的问题是破坏封装
确实,proto或getPrototypeOf打破了对象的封装屏障,并揭示了可能意图隐藏的实现细节。同样,对于所提出的getProperty函数,它使观察者可以访问实现getter/setter属性的函数,这也可以说是反射的本质。-Allen Wirfs-Brock
从实现端提出的一个问题是暴露实现细节(主要是源自DOM的工作方式的担忧,但已通过对多重继承的使用以及转向WebIDL进行了改变)。
另一方面,为对象的原型提供反射访问会对兼容性造成影响,因为它会防止实现引入中间原型而破坏网络。考虑一个例子,只有数字,然后再兼容地引入更具体的数字子类型。- Waldemar Horwat
这个问题也与脚本协调邮件列表中提到的另一个问题有关,即内部隐藏原型在跨帧时相同。这个问题在ES5(和IE8)时已经历史了,当时决定并实施每个帧必须实例化其自己的DOM原型集合。因此,由于这个原因隐藏原型在ES5正式发布时已不再相关。
我看到的共识并不遵循Crockford的解释。大多数情况下,它似乎只是他自己观点的重申。
总之,不提供对对象原型的反射访问并不能真正提供任何安全保障,只会使一些有用的任务变得不太方便。
- Allen Wirfs-Brock
我总体上同意你的观点,并且很高兴听到反射并不是“真正安全”的敌人。
- Brendan Eich
这个的起点是
拟议的 ECMAScript 3.1 静态对象函数:用例和原理(由 Crockford 和 TC39 的其他成员编写)。我引用的后续内容来自
这个 es-discuss 线程,具体来说是
这篇文章和
这篇文章。
__proto__
并不明显是一个巨大的安全问题,但 Brendan Eich 反对添加它,因为它是非标准的,并暴露了不必要的攻击面(Mario Heiderich 在他的博士论文中稍微扩展了一下安全影响);2. Douglas 最早在2008年以明确的方式提出了这个观点。 - Jordan Gray