🤍 前端开发工程师、技术日更博主、已过CET6
🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1
🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》、《前端求职突破计划》
🍚 蓝桥云课签约作者、上架课程《Vue.js 和 Egg.js 开发企业级健康管理项目》、《带你从入门到实战全面掌握 uni-app》
文章目录
- 问题描述
- 原因分析
- 解决方案
- 1. 检查属性的可配置性
- 2. 使用 `Object.defineProperties()` 重新定义属性
- 3. 使用 Proxy 对象
- 实战案例
- 总结
问题描述
在JavaScript开发过程中,开发者经常会遇到 TypeError: Cannot delete property 'xxx' of #<Object>
的错误提示。该错误通常表示在尝试删除一个不可配置(non-configurable)的属性时发生了类型错误。
原因分析
-
不可配置属性:当使用
Object.defineProperty()
或Object.defineProperties()
方法定义的属性被设置为不可配置(non-configurable)时,这些属性不能被删除。例如:const obj = {}; Object.defineProperty(obj, 'fixedProp', { value: 'This is fixed', configurable: false }); delete obj.fixedProp; // 这将抛出 TypeError: Cannot delete property 'fixedProp' of #<Object>
-
全局对象的属性:在全局作用域中,某些属性可能被设置为不可配置,导致无法删除。例如:
delete globalThis.x; // TypeError: Cannot delete property 'x' of #<Object>
-
严格模式下的限制:在严格模式下,尝试删除不可配置的属性会抛出错误。例如:
'use strict'; let obj = {}; Object.defineProperty(obj, 'fixedProp', { value: 'This is fixed', configurable: false }); delete obj.fixedProp; // 抛出 TypeError: Cannot delete property 'fixedProp' of #<Object>
解决方案
1. 检查属性的可配置性
使用 Object.getOwnPropertyDescriptor()
方法来检查属性的描述符,确定其是否可配置。例如:
const obj = {};
Object.defineProperty(obj, 'fixedProp', { value: 'This is fixed', configurable: false });if (Object.getOwnPropertyDescriptor(obj, 'fixedProp').configurable) {delete obj.fixedProp; // 成功删除
} else {console.error('Property is non-configurable');
}
2. 使用 Object.defineProperties()
重新定义属性
如果需要删除一个通过 Object.defineProperties()
定义的属性,可以重新定义该属性,但不包含 getter/setter,从而覆盖旧的属性。例如:
let obj = {};
Object.defineProperties(obj, {myProperty: {get: function() { return this._myProperty; },set: function(value) { this._myProperty = value; }}
});// 假设我们想要删除 getter/setter
delete obj.myProperty; // 这不会起作用,因为属性是不可配置的// 重新定义属性,不包含 getter/setter
Object.defineProperty(obj, 'myProperty', { value: obj._myProperty, writable: true });
// 现在旧的 getter/setter 已经被覆盖
3. 使用 Proxy 对象
另一种方法是使用 Proxy
对象来拦截对属性的访问和删除操作。例如:
let obj = {};
Object.defineProperties(obj, {myProperty: {set: function(value) { this._myProperty = value; }}
});let proxyObj = new Proxy(obj, {deleteProperty(target, prop) {if (prop === 'myProperty') {target._myProperty = undefined;return true;}return Reflect.deleteProperty(target, prop);}
});// 现在你可以通过 proxyObj 访问和删除 myProperty,而不需要 getter/setter
实战案例
假设有一个对象包含一个不可配置的属性,需要删除该属性:
'use strict';
let obj = {};
Object.defineProperty(obj, 'fixedProp', { value: 'This is fixed', configurable: false });try {delete obj.fixedProp; // 这将抛出 TypeError: Cannot delete property 'fixedProp' of #<Object>
} catch (e) {console.error(e); // TypeError: Cannot delete property 'fixedProp' of #<Object>
}
解决方案是使用 Object.getOwnPropertyDescriptor()
检查属性的可配置性:
'use strict';
let obj = {};
Object.defineProperty(obj, 'fixedProp', { value: 'This is fixed', configurable: false });if (Object.getOwnPropertyDescriptor(obj, 'fixedProp').configurable) {delete obj.fixedProp; // 成功删除
} else {console.error('Property is non-configurable');
}
总结
TypeError: Cannot delete property 'xxx' of #<Object>
错误通常是由于尝试删除一个不可配置的属性引起的。通过以下方法可以有效避免该问题:
- 检查属性的可配置性:使用
Object.getOwnPropertyDescriptor()
方法来检查属性是否可配置。 - 重新定义属性:如果需要删除不可配置的属性,可以重新定义该属性,但不包含 getter/setter。
- 使用 Proxy 对象:通过
Proxy
对象拦截对属性的访问和删除操作。
通过这些方法,开发者可以提高代码的健壮性,减少运行时错误,提升应用的稳定性和用户体验。建议开发者定期检查和测试代码,确保所有属性在删除前都是可配置的。