一个属性是否可写可以从它的属性描述符中确定。
您可以使用 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.
首先要做的是检查可写值。如果为真,则该属性是可写的。但是,您还应该检查“值”是否不是函数。
有些属性没有实际值,而是一个 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;
}
结论:
不要这样做。使用列表。