delete

delete 运算符从对象中删除属性。如果属性的值是一个对象,并且不再有对该对象的引用,则该属性所持有的对象最终会自动释放。

¥The delete operator removes a property from an object. If the property's value is an object and there are no more references to the object, the object held by that property is eventually released automatically.

Try it

语法

¥Syntax

js
delete object.property
delete object[property]

注意:该语法允许在 delete 运算符后面使用更广泛的表达式,但只有上述形式才会产生有意义的行为。

¥Note: The syntax allows a wider range of expressions following the delete operator, but only the above forms lead to meaningful behaviors.

参数

¥Parameters

object

对象的名称或计算对象的表达式。

property

要删除的属性。

返回值

¥Return value

true 适用于所有情况,但属性是 own non-configurable 属性时除外,在这种情况下,以非严格模式返回 false

¥true for all cases except when the property is an own non-configurable property, in which case false is returned in non-strict mode.

例外情况

¥Exceptions

TypeError

如果该属性是自己的不可配置属性,则在 严格模式 中抛出。

ReferenceError

如果 objectsuper,则抛出。

描述

¥Description

delete 运算符具有与 typeof 等其他一元运算符相同的 precedence。因此,它接受由更高优先级运算符形成的任何表达式。然而,以下形式会导致 严格模式 中的早期语法错误:

¥The delete operator has the same precedence as other unary operators like typeof. Therefore, it accepts any expression formed by higher-precedence operators. However, the following forms lead to early syntax errors in strict mode:

js
delete identifier;
delete object.#privateProperty;

因为 classes 自动处于严格模式,而 私有属性 只能在类体中合法引用,这意味着私有属性永远不能被删除。虽然 delete identifier 可能有效(如果 identifier 引用全局对象的可配置属性),但你应该避免这种形式并在其前面加上 globalThis 前缀。

¥Because classes are automatically in strict mode, and private properties can only be legally referenced in class bodies, this means private properties can never be deleted. While delete identifier may work if identifier refers to a configurable property of the global object, you should avoid this form and prefix it with globalThis instead.

虽然其他表达方式被接受,但它们不会导致有意义的行为:

¥While other expressions are accepted, they don't lead to meaningful behaviors:

js
delete console.log(1);
// Logs 1, returns true, but nothing deleted

delete 运算符从对象中删除给定的属性。删除成功则返回 true,否则返回 false。与普遍看法不同(可能是由于其他编程语言,如 C++ 中的删除),delete 运算符与直接释放内存无关。内存管理是通过破坏引用间接完成的。有关详细信息,请参阅 内存管理 页。

¥The delete operator removes a given property from an object. On successful deletion, it will return true, else false will be returned. Unlike what common belief suggests (perhaps due to other programming languages like delete in C++), the delete operator has nothing to do with directly freeing memory. Memory management is done indirectly via breaking references. See the memory management page for more details.

考虑以下场景很重要:

¥It is important to consider the following scenarios:

  • 如果你尝试删除的属性不存在,则 delete 将不起作用并返回 true
  • delete 只对自身属性有影响。如果对象的原型链上存在同名属性,那么删除后,该对象将使用原型链上的属性。
  • 无法删除不可配置的属性。这包括 MathArrayObject 等内置对象的属性以及使用 Object.defineProperty() 等方法创建为不可配置的属性。
  • 删除变量,包括函数参数,永远不会起作用。delete variable 在严格模式下会抛出 SyntaxError,在非严格模式下不起作用。
    • 任何用 var 声明的变量都不能从全局作用域或函数作用域中删除,因为虽然它们可以附加到 全局对象,但它们是不可配置的。
    • 任何用 letconst 声明的变量都不能从定义它们的作用域中删除,因为它们没有附加到对象。

示例

¥Examples

使用删除

¥Using delete

注意:以下示例仅使用非严格模式的功能,例如隐式创建全局变量和删除标识符,这些功能在严格模式下是禁止的。

¥Note: The following example uses non-strict-mode only features, like implicitly creating global variables and deleting identifiers, which are forbidden in strict mode.

js
// Creates the property empCount on the global scope.
// Since we are using var, this is marked as non-configurable.
var empCount = 43;

// Creates the property EmployeeDetails on the global scope.
// Since it was defined without "var", it is marked configurable.
EmployeeDetails = {
  name: "xyz",
  age: 5,
  designation: "Developer",
};

// delete can be used to remove properties from objects.
delete EmployeeDetails.name; // returns true

// Even when the property does not exist, delete returns "true".
delete EmployeeDetails.salary; // returns true

// EmployeeDetails is a property of the global scope.
delete EmployeeDetails; // returns true

// On the contrary, empCount is not configurable
// since var was used.
delete empCount; // returns false

// delete also does not affect built-in static properties
// that are non-configurable.
delete Math.PI; // returns false

function f() {
  var z = 44;

  // delete doesn't affect local variable names
  delete z; // returns false
}

删除和原型链

¥delete and the prototype chain

在下面的示例中,我们删除对象自己的属性,而原型链上有同名的属性:

¥In the following example, we delete an own property of an object while a property with the same name is available on the prototype chain:

js
function Foo() {
  this.bar = 10;
}

Foo.prototype.bar = 42;

const foo = new Foo();

// foo.bar is associated with the
// own property.
console.log(foo.bar); // 10

// Delete the own property within the
// foo object.
delete foo.bar; // returns true

// foo.bar is still available in the
// prototype chain.
console.log(foo.bar); // 42

// Delete the property on the prototype.
delete Foo.prototype.bar; // returns true

// The "bar" property can no longer be
// inherited from Foo since it has been
// deleted.
console.log(foo.bar); // undefined

删除数组元素

¥Deleting array elements

删除数组元素时,数组 length 不受影响。即使你删除了数组的最后一个元素,这也成立。

¥When you delete an array element, the array length is not affected. This holds even if you delete the last element of the array.

delete 运算符删除数组元素时,该元素不再位于数组中。在以下示例中,trees[3]delete 一起被删除。

¥When the delete operator removes an array element, that element is no longer in the array. In the following example, trees[3] is removed with delete.

js
const trees = ["redwood", "bay", "cedar", "oak", "maple"];
delete trees[3];
console.log(3 in trees); // false

这将创建一个带有空槽的 稀疏数组。如果你希望数组元素存在但具有未定义的值,请使用 undefined 值而不是 delete 运算符。在以下示例中,trees[3] 被分配了值 undefined,但数组元素仍然存在:

¥This creates a sparse array with an empty slot. If you want an array element to exist but have an undefined value, use the undefined value instead of the delete operator. In the following example, trees[3] is assigned the value undefined, but the array element still exists:

js
const trees = ["redwood", "bay", "cedar", "oak", "maple"];
trees[3] = undefined;
console.log(3 in trees); // true

相反,如果你想通过更改数组内容来删除数组元素,请使用 splice() 方法。在以下示例中,使用 splice() 从数组中完全删除 trees[3]

¥If instead, you want to remove an array element by changing the contents of the array, use the splice() method. In the following example, trees[3] is removed from the array completely using splice():

js
const trees = ["redwood", "bay", "cedar", "oak", "maple"];
trees.splice(3, 1);
console.log(trees); // ["redwood", "bay", "cedar", "maple"]

删除不可配置的属性

¥Deleting non-configurable properties

当一个属性被标记为不可配置时,delete 不会有任何作用,并且会返回 false。在严格模式下,这将引发 TypeError

¥When a property is marked as non-configurable, delete won't have any effect, and will return false. In strict mode, this will raise a TypeError.

js
const Employee = {};
Object.defineProperty(Employee, "name", { configurable: false });

console.log(delete Employee.name); // returns false

var 创建无法使用 delete 运算符删除的不可配置属性:

¥var creates non-configurable properties that cannot be deleted with the delete operator:

js
// Since "nameOther" is added using with the
// var keyword, it is marked as non-configurable
var nameOther = "XYZ";

// We can access this global property using:
Object.getOwnPropertyDescriptor(globalThis, "nameOther");
// {
//   value: "XYZ",
//   writable: true,
//   enumerable: true,
//   configurable: false
// }

delete globalThis.nameOther; // return false

在严格模式下,这会引发异常。

¥In strict mode, this would raise an exception.

删除全局属性

¥Deleting global properties

如果全局属性是可配置的(例如,通过直接属性分配),则可以将其删除,并且随后将它们作为全局变量引用将产生 ReferenceError

¥If a global property is configurable (for example, via direct property assignment), it can be deleted, and subsequent references to them as global variables will produce a ReferenceError.

js
globalThis.globalVar = 1;
console.log(globalVar); // 1
// In non-strict mode, you can use `delete globalVar` as well
delete globalThis.globalVar;
console.log(globalVar); // ReferenceError: globalVar is not defined

规范

Specification
ECMAScript Language Specification
# sec-delete-operator

¥Specifications

浏览器兼容性

BCD tables only load in the browser

¥Browser compatibility

也可以看看