在this video(大约31分钟)中,Crockford说他们(代表ECMAScript委员会发言)建议不使用Object.getPrototypeOf
。他的解释是,它并不是真正意义上的普通开发人员,而是用于像Caja这样的东西,可能会将其从Object
中删除,以防止您访问它。
Crockford在他关于如何使用JS(我们不能全部?)的观点中有时会非常自以为是,所以我想知道这是否真的是ES委员会的全部推荐,或者它是否只是Crockford的一个个人意见。是否有人阅读任何官方声明警告不要使用Object.getPrototypeOf
?这对我来说真的听起来很糟糕:(但我没有看到MDN页面上的任何信息警告它的使用,如果真的那么糟糕,我会期待有通知。
答案 0 :(得分:15)
他的推理非常糟糕。它(和Object.getOwnPropertyNames
)不仅仅是为了使用Caja而添加的。 Caja也不会删除它们! Caja拦截Object.getOwnPropertyNames
以实现WeakMap
(my shim也会这样做),据我所知,它不会修改getPrototypeOf。实际上,无论如何都是毫无意义的,因为Object.getPrototypeOf(o)
与o.__proto__
是同一个东西,它在IE之外的每个浏览器中实现,并且不能(当前)关闭。这意味着删除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来解决)。
另一方面,提供对对象原型的反射访问对兼容性有害,因为它可以防止实现在不破坏Web的情况下引入中间原型。考虑只有数字的例子,然后兼容地引入更具体的数字子。 - Waldemar Horwat
这个问题还与脚本协调邮件列表中提到的另一个问题有关,内部隐藏原型是相同的跨框架。这个问题也是ES5(和IE8)的历史问题,在这个问题上,每个框架都必须实例化自己的DOM原型集。因此,ES5正式发布时,因此隐藏原型已不再适用。
我看到的共识并不遵循克罗克福德的解释。大多数情况下,这似乎只是对自己意见的重述。
总之,不提供对象原型的反射访问并不真正提供任何真正的安全性,它只是使一些有用的任务不太方便。 -Allen Wirfs-Brock
我总体上同意你的看法,很高兴听到反思不是“真正的安全”的敌人。 -Brendan Eich
起点是Proposed ECMAScript 3.1 Static Object Functions: Use Cases and Rationale(由Crockford和其他人在TC39上撰写)。我从中引用引文的后续内容是this es-discuss thread。具体为this post和this post。