翻译正在进行中。

 delete 操作符能删除对象的某个属性。

语法

delete expression

 expression 应该是一个对象的属性引用,例如:

delete object.property 
delete object['property']

参数

object
对象的名称,或执行结果为对象的表达式。
property
要删除的属性。

返回值

对于所有情况都是true,除非属性是一个自己的不可配置属性,在这种情况下,非严格模式返回 false。

Exceptions

假如要删除的属性是对象自身的   non-configurable 属性,那么在  strict mode 下就会抛出{jsxref("Global_objects/SyntaxError")}} 。

描述

跟一般人的认为的不一样的是,delete 操作符不会直接释放内存。其释放内存是通过打破引用间接完成的,可查看内存管理了解更多。

delete 操作符会从某个对象上移除指定属性。成功删除的时候回返回 true,否则返回 false。但是,重要的是要考虑以下情况:

  • If the property which you are trying to delete does not exist, delete will not have any effect and will return true
  • If a property with the same name exists on the object's prototype chain, then, after deletion, the object will use the property from the prototype chain (in other words, delete only has an effect on own properties).如果 delete 操作符删除成功,则被删除的属性将从所属的对象上彻底消失。然后,如果该对象的原型链上有一个同名属性,则该对象会从原型链上继承该同名属性。
  • Any property declared with var cannot be deleted from the global scope or from a function's scope.
    • As such, delete cannot delete any functions in the global scope (whether this is part from a function definition or a function expression).
    • Functions which are part of an object (apart from the global scope) can be deleted with delete.
  • Any property declared with let or const cannot be deleted from the scope within which they were defined.
  • Non-configurable properties cannot be removed. This includes properties of built-in objects like Math, Array, Object and properties that are created as non-configurable with methods like Object.defineProperty().

The following snippet gives a simple example:

var Employee = {
  age: 28,
  name: 'abc',
  designation: 'developer'
}

console.log(delete Employee.name);   // returns true
console.log(delete Employee.age);    // returns true

// When trying to delete a property that does 
// not exist, true is returned 
console.log(delete Employee.salary); // returns true

Non-configurable 属性

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 SyntaxError.

var Employee = {};
Object.defineProperty(Employee, 'name', {configurable: false});

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

varlet and const create non-configurable properties that cannot be deleted with the delete operator:

var nameOther = 'XYZ';

// We can access this global property using:
Object.getOwnPropertyDescriptor(window, 'nameOther');  

// output: Object {value: "XYZ", 
//                  writable: true, 
//                  enumerable: true,
//                  configurable: false}

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

delete nameOther;   // return false

In strict mode, this would have raised an exception.

Strict vs. non-strict mode

When in strict mode, if delete is used on a direct reference to a variable, a function argument or a function name, it will throw a SyntaxError.

Any variable defined with var is marked as non-configurable. In the following example, salary is non-configurable and cannot be deleted. In non-strict mode, the delete operation will return false.

function Employee() { 
  delete salary;
  var salary;
}

Employee();

Let's see how the same code behaves in strict mode. Instead of returning false, the statement raises a SyntaxError.

"use strict";

function Employee() {
  delete salary;  // SyntaxError
  var salary;        
}

// Similarly, any direct access to a function
// with delete will raise a SyntaxError

function DemoFunction() {
  //some code
}

delete DemoFunction; // SyntaxError

示例

// creates the property adminName on the global scope
adminName = 'xyz';            

// creates the property empCount on the global scope
// Since we are using var, this is marked as non-configurable. The same is true of let and const.
var empCount = 43;

EmployeeDetails = {
  name: 'xyz',
  age: 5,
  designation: 'Developer'
};

// adminName is a property of the global scope.
// It can be deleted since it is created without var.
// Therefore, it is configurable.
delete adminName;       // returns true

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

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

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

// delete does not affect built-in static properties
delete Math.PI; // returns false 

// EmployeeDetails is a property of the global scope.
// Since it defined without "var", it is marked configurable
delete EmployeeDetails;   // returns true

function f() {
  var z = 44;

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

删除和原型链

在下面的示例中,我们删除一个对象的自己的属性,而具有相同名称的属性在原型链上可用:

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

Foo.prototype.bar = 42;

var foo = new Foo();

// Returns true, since the own property
// has been deleted on the foo object
delete foo.bar;           

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

// We delete the property on the prototype
delete Foo.prototype.bar; 

// logs "undefined" since the property
// is no longer inherited
console.log(foo.bar);

你能删除一个对象从原型继承而来的属性(你可以从原型上直接删掉它).

 function Foo(){}
 Foo.prototype.bar = 42;
 let foo = new Foo();

 // 无效的操作
 delete foo.bar;       
 // true     
   
 // 继承的属性
 console.log(foo.bar); 
 // 42   
    
 // 直接删除原型上的属性
 delete Foo.prototype.bar;
 // true
 
 // 已经没有继承的属性
 console.log(foo.bar); 
 // undefined 
          

删除数组元素

当你删除一个数组元素时,数组的 length 属性并不会变小。即便你删除了数组的最后一个元素也是如此。

当用 delete 操作符删除一个数组元素时,被删除的元素已经不再属于该数组。下面的例子中用 delete 删除了 trees[3]

var trees = ["redwood","bay","cedar","oak","maple"];
delete trees[3];
if (3 in trees) {
   // 这里不会执行
}

如果你想让一个数组元素继续存在但是其值是 undefined,那么可以使用将 undefined 赋值给这个元素而不是使用 delete。下面的例子中,trees[3] 被赋值为 undefined,但该元素仍然存在。

var trees = ["redwood","bay","cedar","oak","maple"];
trees[3] = undefined;
if (3 in trees) {
   // 这里会被执行
}

规范

Specification Status Comment
ECMAScript Latest Draft (ECMA-262)
The delete Operator
Draft  
ECMAScript 2015 (6th Edition, ECMA-262)
The delete Operator
Standard  
ECMAScript 5.1 (ECMA-262)
The delete Operator
Standard  
ECMAScript 1st Edition (ECMA-262)
The delete Operator
Standard Initial definition. Implemented in JavaScript 1.2.

浏览器兼容性

Feature Chrome Firefox (Gecko) Internet Explorer Opera Safari
Basic support (Yes) (Yes) (Yes) (Yes) (Yes)
Temporal dead zone ? 36 (36) ? ? ?
Feature Android Chrome for Android Firefox Mobile (Gecko) IE Mobile Opera Mobile Safari Mobile
Basic support (Yes) (Yes) (Yes) (Yes) (Yes) (Yes)
Temporal dead zone ? ? 36.0 (36) ? ? ?

跨浏览器问题

虽然 ECMAScript 规定了对象的遍历顺序是由对象定义时属性的书写顺序决定的。(译者注:ES5已经对遍历机制做了调整,重新规定:属性遍历的顺序是没有被规定的), 大部分浏览器都依照这个规定,先添加的属性先被遍历(除了从原型上继承的属性)(译者注:Chrome和Opera已经遵循了ES5的新规定,具体请看)。但是,在 Internet Explorer 中,使用 delete 删除一个属性后,奇怪的事情发生了,如果被删除的属性重新被添加,那么遍历时,该属性的顺序会是上次删除前的那个位置所应该有的顺序,而不是出现在遍历的最后一个。

所以,如果你想让对象的遍历顺序兼容所有的浏览器,那么你可以使用两个数组来模拟 (一个做为keys,一个做为 values), 或者建立一个由单一属性对象组成的数组,等。

相关链接

文档标签和贡献者

 此页面的贡献者: Ende93, xgqfrms-GitHub, xwartz, AlexChao, ziyunfei, teoli
 最后编辑者: Ende93,