这是一个关于使用纯Javascript(而不是jQuery等(与DOM交互的问题
我的最终目标是只收集任何给定DOM元素的可写属性的当前值,所以我想跳过该元素的所有不可写属性。
虽然我可以浏览规范并创建一个列表,但规范会发生变化,所以我想动态地(尽可能高效地(进行操作。
我已经搜索过了,但没有找到任何建议,所以非常欢迎。
PSEUDOCODE:我需要一种实现is_writeable(元素(->下方代码中的布尔值
let myObject = {};
for (propertyName in HTMLElement) {
if(is_writable(HTMLElement[propertyName])){
myObject[propertyName] = HTMLElement[propertyName];
}
}
属性是否可写可以从其属性描述符中确定。您可以使用object.getOwnPropertyDescriptor((来获取对象的属性描述符。但是,此函数只能找到对象自己的属性。
因此,我们需要一个函数来搜索对象的原型链,直到它找到我们要查找的属性并返回属性描述符:
function findPrototypeProperty(object, propertyName){
while (object && object.constructor && object.constructor.name !== 'Object'){
let desc = Object.getOwnPropertyDescriptor(object, propertyName);
if(desc){
return desc;
}
object = Object.getPrototypeOf(object);
}
return null;
}
属性描述符是最多可以包含6个值的对象(从MDN复制(:
value - The value associated with the property (data descriptors only).
writable - true if and only if the value associated with the property may be changed (data descriptors only).
get - A function which serves as a getter for the property, or undefined if there is no getter (accessor descriptors only).
set - A function which serves as a setter for the property, or undefined if there is no setter (accessor descriptors only).
configurable - true if and only if the type of this property descriptor may be changed and if the property may be deleted from the corresponding object.
enumerable - true if and only if this property shows up during enumeration of the properties on the corresponding object.
要做的第一件事是检查可写值。如果为true,则该属性是可写的。但是,您还应该检查"value"是否不是函数。
有些属性没有实际值,而是使用getter和setter函数。如果一个属性有一个set函数,那么它通常也是可写的。
这就是is_writeable函数的样子:
function is_writeable(object, propertyName){
let desc = findPrototypeProperty(object, propertyName);
if(!desc){
return false;
}
if(desc.writable && typeof desc.value !== "function"){
return true;
}
return !!desc.set;
}
结论:不要这么做。用一个清单
使用document.querySelectorAll
检查DOM Elements
的特定属性
像这样:
document.querySelectorAll('*[readonly]')
将返回具有readonly
属性的所有元素的数组。
一种方法是使用try/catch:
const is_writable = (element, propName) => {
const originalValue = element[propName]
try {
element[propName] = 1 // set it to an arbitrary value
} catch () {
return false
}
element[propName] = originalValue
return true
}