意外的'删除'返回值

Unexpected 'delete' return value

本文关键字:返回值 删除 意外      更新时间:2023-09-26

我有以下代码段,其中最后一个"delete"用法返回了一个意外值。

function Shape() {
  this.a = 10;
}
Shape.prototype.a = 20;
var s = new Shape();
console.log(s.a); // 10
delete s.a; //true
console.log(s.a) // 20
delete s.a; //true
console.log(s.a); // 20

即使最终的"delete s.a"返回true,"s.a"的值仍然返回20。

如果我们不能通过引用对象来删除原型上的对象(在本例中为"),为什么delete关键字返回true?

其次,

delete Shape.prototype.a; // true

给出true,并且该属性确实已从Shape.prototype中删除。但是有什么方法可以通过对象引用的删除Shape.prototype.a吗?

delete关键字的返回值并不能指示删除操作是否确实删除了字段。来自MDN关于删除关键字的文章:

返回值

如果属性是自己的不可配置属性,则以严格模式抛出属性(在非严格中返回false)。在所有其他情况下返回true案例。

在您的情况下,s.a不是自己的属性,因此delete将始终返回true。属性是否在原型链中找到并不重要。例如:

delete {}.xyz; // also returns `true`.

你不应该改变原型,因为它会破坏JavaScript引擎为你改进性能所做的所有优化。然而,如果你真的想,你可以使用这个功能:

function deepDelete(o,key) {
  while (o) {
    delete o[key];
    o = Object.getPrototypeOf(o);
  }
}

示例:

function S(){}
S.prototype.a = 8;
var s = new S();
s.a = 9;
console.log(s.a); // 9
delete s.a;
console.log(s.a); // 8
deepDelete(s, 'a');
console.log(s.a); // undefined

function Shape() {
  //this.a = 10;
}
Shape.prototype.a = 20;
var s = new Shape();
console.log(s.a);
delete Shape.prototype.a;
console.log(s.a); 

正如MDN所引用的,以及在hege_hegedus的回答中所提到的

返回值

如果属性是自己的不可配置属性,则以严格模式抛出属性(在非严格中返回false)。在所有其他情况下返回true案例。

底线是delete是一个运算符,而不是一个方法,它只是从Object中删除一个属性,aShape.prototype的属性,而不是类Shape的对象的属性,所以你需要删除它,而不是delete s.a

delete方法只能删除对象自己的属性,而不能删除原型的属性。当您删除对象中不存在的属性时,它将返回ture;但是,以下情况将返回false:

delete Object.prototype; //renturn false; property can't set
var x=1;
delete this.x; //return flase;can not delete a global var
function f(){}
delete this.f; //return false; can not delete a global function