为何CSSStyleDeclaration对象中Object.hasOwn与Reflect.ownKeys结果不一致?
关于CSSStyleDeclaration对象的属性检测矛盾问题
以下表达式结果均为true:
'z-index' in getComputedStyle(document.body) // true Reflect.has(getComputedStyle(document.body), 'z-index') // true
甚至检测自有属性的方法也返回true:
getComputedStyle(document.body).hasOwnProperty('z-index') // true Object.hasOwn(getComputedStyle(document.body), 'z-index') // true
但下面这个表达式结果为false:
Reflect.ownKeys(getComputedStyle(document.body)).includes('z-index') // false
这就出现了矛盾:Object.hasOwn(x, y)判定目标是自有属性,但Reflect.ownKeys(x)却找不到对应的属性名。
而且这个问题并非只读的计算样式对象独有,可读写的元素style对象也存在同样情况:
Object.hasOwn(document.body.style, 'z-index') // true Reflect.ownKeys(document.body.style).includes('z-index') // false
MDN文档提到:
CSS属性值可通过getPropertyValue(propName) API或直接通过对象索引访问,例如obj['z-index']或obj.zIndex。
这种索引访问是为了便捷性,但根据ECMAScript规则,为什么会出现Object.hasOwn和Reflect.ownKeys的结果差异?
原因解释
这是因为CSSStyleDeclaration是宿主对象(由浏览器环境提供,而非ECMAScript标准原生对象),它不需要严格遵循ECMAScript的所有规则。
具体来说,这类对象实现了自定义的内部方法:
- [[HasProperty]]:当使用
in、Reflect.has、hasOwnProperty、Object.hasOwn时,会触发这个方法,它会直接映射CSS属性名(比如z-index)并返回true,即使这个属性并没有被作为真正的自有属性存储在对象上。 - [[OwnPropertyKeys]]:
Reflect.ownKeys会调用这个方法,而浏览器实现的这个方法只返回对象的原生自有属性(比如cssText、length等),不会包含那些映射的CSS属性名。
简单说,浏览器为了让开发者能像访问普通对象属性一样访问CSS属性,给CSSStyleDeclaration做了特殊的属性访问拦截,但并没有把这些CSS属性名真正加入到对象的自有属性键列表中。
内容的提问来源于stack exchange,提问作者yg-i
相关产品推荐
相关产品推荐

