Chrome为何在全局对象原型链中添加额外全局对象副本?
通过阅读Web IDL规范中关于创建新**platform objects(平台对象)**的章节,我们了解到全局对象创建时,其[[prototype]]会被设置为全局interface object(接口对象)的instance prototype object(实例原型对象)(该对象在创建interface object时已提前生成)。
查看关于创建interface prototype objects(接口原型对象)的章节可知,全局对象的[[prototype]]的[[prototype]]会被设置为named properties object(命名属性对象)。
该对象的[[prototype]]又会链接到全局接口所继承的对象。
IDL和HTML规范定义的全局对象原型链如下:
window -> Window.prototype -> WindowProperties (the *named properties object*) -> EventTarget.prototype -> Object.prototype -> null
Firefox会创建上述完整的原型链,但Chrome似乎在链中添加了一个额外的全局对象副本。在Chrome中执行console.dir(window),控制台显示:
window -> window -> Window.prototype -> WindowProperties (the *named properties object*) -> EventTarget.prototype -> Object.prototype -> null
有趣的是,在Chrome中执行console.dir(Object.getPrototypeOf(window))确实会输出Window.prototype,因此奇怪之处在于链开头添加的第一个“全局对象副本”。
为何Chrome会有此行为?该行为是否有相关规范依据?
这其实是Chrome开发者工具的显示优化处理,并非实际原型链中真的存在额外的全局对象副本。
核心原因是window对象本身存在自引用特性——window.window === window,Chrome的console.dir()在展示全局对象的原型链时,特意把这个自引用属性作为链的第一个节点显示,目的是让开发者更直观地感知全局对象的这一特性,但这完全不改变实际的原型链结构。
从规范角度来说,这种显示行为没有对应的强制要求,属于浏览器开发者工具的自定义实现。实际通过Object.getPrototypeOf()、Reflect.getPrototypeOf()等标准API获取的原型链,完全符合Web IDL和HTML规范的定义:window的直接原型就是Window.prototype,不存在额外的中间对象。
Chrome这么做的本质是帮助开发者快速识别全局对象的自引用特性,避免混淆全局对象本身和它的原型层级。
内容的提问来源于stack exchange,提问作者Magnus

