如何检测DOM元素属性是否只读?求纯JS动态筛选可写属性方案
纯JS动态判断DOM元素可写属性并收集值
嘿,这个需求确实很合理——硬编码属性列表太容易过时,动态检测才是长久之计。我来给你分享几个靠谱的实现思路:
核心:实现isWritable函数
要判断一个属性是否可写,我们需要结合JS的属性描述符机制,因为DOM元素的属性既有数据属性(带writable标识),也有访问器属性(通过get/set方法控制)。
方法1:通过属性描述符检测(推荐,无副作用)
这个方法直接读取属性的配置信息,不会修改元素,也不会触发任何副作用:
function isWritable(element, propertyName) { let currentElement = element; let descriptor; // 遍历原型链,直到找到属性的描述符或者到达原型链顶端 while (currentElement !== null && !descriptor) { descriptor = Object.getOwnPropertyDescriptor(currentElement, propertyName); currentElement = Object.getPrototypeOf(currentElement); } if (!descriptor) return false; // 属性不存在 // 数据属性:writable为true;访问器属性:存在setter方法 return descriptor.writable === true || typeof descriptor.set === 'function'; }
方法2:通过赋值测试判断(简单但有风险)
如果不想处理原型链和描述符的细节,可以尝试给属性赋值一个临时值,看是否能成功。但要注意:这个方法会触发属性的setter逻辑,可能带来副作用(比如修改DOM结构),所以只适合无副作用的属性:
function isWritableByAssignment(element, propertyName) { if (!(propertyName in element)) return false; const originalValue = element[propertyName]; // 用Symbol做测试值,避免和原有值冲突 const testValue = Symbol('test-writable-check'); try { element[propertyName] = testValue; // 赋值后值变化则说明可写 const writable = element[propertyName] === testValue; // 恢复原值 element[propertyName] = originalValue; return writable; } catch (e) { // 赋值抛出异常,说明不可写 return false; } }
收集可写属性的完整实现
注意你伪代码里遍历的是HTMLElement构造函数的静态属性,但实际需求应该是收集具体DOM元素实例的可写属性。这里是完整的收集函数:
function collectWritableElementProperties(element) { const writableProps = {}; let current = element; // 遍历元素的原型链,直到HTMLElement(避免收集Object的属性) while (current && current instanceof HTMLElement) { // 获取当前对象的所有自有属性(包括不可枚举的) const props = Object.getOwnPropertyNames(current); props.forEach(prop => { // 避免重复收集原型链上的属性 if (!(prop in writableProps) && isWritable(current, prop)) { try { // 有些属性访问可能抛出异常(比如受限制的浏览器属性),所以加try-catch writableProps[prop] = current[prop]; } catch (e) { console.warn(`跳过无法访问的属性 ${prop}:`, e); } } }); current = Object.getPrototypeOf(current); } return writableProps; } // 使用示例 const myElement = document.querySelector('#my-element'); const myObject = collectWritableElementProperties(myElement);
额外注意点
- 有些属性虽然描述符标记为可写,但实际访问或赋值可能受浏览器限制(比如某些隐私相关属性),所以
try-catch是必要的。 - 如果你只需要收集可枚举的属性,可以把
Object.getOwnPropertyNames换成Object.keys,但会漏掉一些不可枚举但可写的属性。
内容的提问来源于stack exchange,提问作者user2002907
相关产品推荐
相关产品推荐

