delete只对对象自有可配置属性有效,不能删除变量、函数声明或不可配置属性;赋值undefined不删除属性,而delete真正移除属性;数组中delete产生空槽,应使用splice等方法。

delete 运算符能删掉对象属性,但不能删变量或函数声明
直接说结论:delete 只对对象的**自有可配置属性**有效。它不是“删除变量”的工具,也不能删 var、let、const 声明的绑定,也不能删函数声明(function foo() {})本身。
常见误解是以为 delete obj.key 类似于 obj.key = undefined —— 实际上二者语义完全不同:delete 真正移除属性(从对象内部属性列表中剔除),而赋值 undefined 只是改值,属性依然存在、仍会被 for...in 遍历到。
-
delete返回布尔值:true表示删除成功(或目标本就不存在),false表示失败(如属性不可配置) - 严格模式下,尝试删除不可配置属性会抛出
TypeError;非严格模式下静默失败(返回false) - 全局作用域下用
var声明的变量,其属性被自动设为不可配置,所以delete window.xxx一定失败
哪些属性删不掉?看 [[Configurable]] 特性
对象属性是否可删,取决于它的 [[Configurable]] 内部特性。默认情况下:
-
Object.defineProperty(obj, 'key', { value: 1 })创建的属性,configurable默认为false→delete失败 -
obj.key = 1或obj['key'] = 1创建的属性,configurable默认为true→delete成功 - 访问器属性(
get/set)若未显式设configurable: true,也删不掉
const obj = {};
Object.defineProperty(obj, 'locked', { value: 42 });
console.log(delete obj.locked); // false(不可配置)
obj.normal = 'ok';
console.log(delete obj.normal); // true(可配置)
delete 对数组的影响:不要用来删数组元素
delete arr[2] 不会改变数组长度,也不会移动后续元素,而是把对应位置变成“空槽”(empty),该索引在 for...in 中仍会出现,但 arr[2] 访问返回 undefined,且 Array.isArray(arr) 仍为 true。
立即学习“Java免费学习笔记(深入)”;
- 这不是你想要的“删除数组元素”行为 —— 应该用
splice()、filter()或pop()/shift() -
delete后的数组用forEach、map会跳过空槽,但for...in仍会遍历到那个索引 - 性能上,
delete会让 V8 引擎将数组退化为“字典模式”,后续操作变慢
const arr = ['a', 'b', 'c', 'd']; delete arr[2]; console.log(arr); // ['a', 'b',, 'd'] console.log(arr.length); // 4(没变!) console.log('2' in arr); // false(但注意:这和 hasOwnProperty 不同)
替代方案:Reflect.deleteProperty 更可控
Reflect.deleteProperty(obj, key) 是 delete 的函数式封装,行为完全一致,但它更适合作为高阶操作使用(比如配合 Proxy 或统一错误处理)。它不会在严格模式下抛异常,而是始终返回布尔值,便于逻辑判断。
- 和
delete一样,只影响自有可配置属性 - 不触发语法错误,适合动态键名场景(
Reflect.deleteProperty(obj, someKey)比delete obj[someKey]在某些静态检查工具中更友好) - 无法绕过不可配置限制 —— 它只是把
delete操作“函数化”,不是增强版
const obj = { a: 1, b: 2 };
const key = 'a';
console.log(Reflect.deleteProperty(obj, key)); // true
console.log(obj); // { b: 2 }
真正容易被忽略的是:很多开发者在循环中边遍历边 delete 对象属性,却没意识到这不会影响当前遍历顺序(因为 for...in 遍历的是属性快照,不是实时结构),也不影响 Object.keys() 的结果(它只返回可枚举自有属性,且生成时已确定)。要安全地批量删属性,先收集键名再统一删,比边遍历边删更可靠。











