如果您想要一个内置的解决方案,您可以添加一个类似于Object.defineProperties() 的实用程序函数,这样您就可以向给定对象添加属性,但现在也可以通过提交null 属性来删除属性描述符。
如果属性描述符不是对象,Object.defineProperties() 会抛出错误,因此我们可以安全地使用“假”值来指示要删除该属性。
代码如下:
function unDefineProperties(obj, propertyDescriptors) {
const [normalDescriptors, toBeDeletedDescriptors] =
partition(Object.entries(propertyDescriptors),([_, descriptor]) => descriptor);
Object.defineProperties(obj, Object.fromEntries(normalDescriptors));
toBeDeletedDescriptors.forEach(([name, _]) => delete obj[name]);
return obj;
}
函数名应该读作“(un)define properties”,即“define or delete properties”。
它使用实用函数partition(定义在下面的代码 sn-p 中,借用自 this answer)。
然后它调用Object.defineProperties(),并使用从“正常”条目重构的属性描述符对象。
之后(因为第一步可能由于不正确的属性描述符而失败),所有“待删除”条目删除obj中的相应属性。
最后,obj 被返回,以模仿 Object.defineProperties() 的便捷行为。
生成的函数与原始 Object.defineProperties() 兼容(当然除了“虚假”属性描述符的行为),因此可以用作原始函数的替代品。如果您想这样做,为了保持一致性,您还应该将Object.defineProperty()(单数!)替换为类似的函数,该函数通过删除相应的属性来处理“虚假”属性描述符(留给读者作为练习;-)) .
下面是完整的代码和用法示例:
function partition(array, filter) {
let pass = [], fail = [];
array.forEach((e, idx, arr) => (filter(e, idx, arr) ? pass : fail).push(e));
return [pass, fail];
}
function unDefineProperties(obj, propertyDescriptors) {
const [normalDescriptors, toBeDeletedDescriptors] =
partition(Object.entries(propertyDescriptors),([_, descriptor]) => descriptor);
Object.defineProperties(obj, Object.fromEntries(normalDescriptors));
toBeDeletedDescriptors.forEach(([name, _]) => delete obj[name]);
return obj;
}
// Usage example:
const obj = { a: 'A', b: 'B', c: 'C'};
unDefineProperties(obj, {
a: null,
c: null,
d: { value: "D", enumerable: true }
});
console.log(obj); // logs { "b": "B", "d": "D" }