前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[译] 弄明白JS中的delete操作符

[译] 弄明白JS中的delete操作符

作者头像
腾讯IVWEB团队
发布2020-06-28 10:40:45
1.1K0
发布2020-06-28 10:40:45
举报

原文: Understanding the Delete Operator in JavaScript - Chidume Nnambi

学习与理解delete操作符如何处理可变更与不可变更属性, 以及一些别的东西.

delete操作符

根据ECMA的定义与解释:

Delete(O, P)

这个方法常常被用来移除一些对象中的特定的属性. 如果属性本身是不可变更的, 那么它将抛出一个错误.

这个操作符在调用时被传入O - 要变更的对象, P - 要移除的属性的key.

代码语言:javascript
复制
let obj = {
    d: 88
}

console.log(obj.d);
delete obj.d;
console.log(obj.d);

我们创建了一个包含d属性, 且值为88的对象obj. 首先我们打印输出d的值, 很显然会出现88. 然后我们通过delete操作符来移除这个属性, 然后我们在打印它. 结果将会是undefined.

代码语言:javascript
复制
88
undefined

undefined是JS中用来表示非值的一个基本数据类型, 意味着数据被定义过了, 但尚未被赋值. 所以当通过delete删除了对象的一个属性之后, 这个属性的值就会变成undefined.

不可变更(non-configuration)属性与delete

delete操作符只会对可变更(configuration)属性起作用. delete不能移除对象的一个不可变更的属性.

我们的obj对象是可变更的, 所以d属性能够被移除. 如果我们定义一个不可变更的属性, 那么delete就不能删除这个属性:

代码语言:javascript
复制
let obj = {
    d: 88
}

Object.defineProperty(obj, d, { configurable: false });

console.log(obj.d);
delete obj.d;
console.log(obj.d);
代码语言:javascript
复制
88
88

可以看到, 属性d并没有被移除. 我们通过Object#defineProperty方法把d属性设置为不可变更的, 只需要把configurable设置为false就行.

默认情况下, 对象的属性都是可变更的.

代码语言:javascript
复制
let obj = {
    d: 88
}

console.log(Object.getOwnPropertyDescriptor(obj, 'd'));
代码语言:javascript
复制
{ value: 88,
  writable: true,
  enumerable: true,
  configurable: true }

之后如果通过Object#defineProperty方法来将configurable设置为false, 这个属性就不会被delete操作符删除了.

var, let, const与delete

var, let, const声明的属性(变量)都是不可变更的, 因此它们声明的属性(变量)也不能通过delete来进行删除.

代码语言:javascript
复制
const a = 1;
let b = 2;
var c = 3;
console.log(a, b, c);
delete a;
delete b;
delete c;
console.log(a, b, c);
代码语言:javascript
复制
1 2 3
1 2 3

函数与delete

函数(Function)也不能通过delete来进行删除

代码语言:javascript
复制
function func() {
    console.log('inside func);
}

delete func;
func();
代码语言:javascript
复制
inside func

但是, 作为属性被定义的函数是可以被删除的

代码语言:javascript
复制
var obj = {
    d: function() {
        console.log('inside obj.d function');
    }
}

obj.d();
delete obj.d;
obj.d();
代码语言:javascript
复制
inside obj.d function

TypeError: obj.d is not a function

与普通的属性一样, 如果这个属性被设置为不可变更的, 那么这个属性也不能被delete操作符删除

代码语言:javascript
复制
const obj = {
    d: function() {
        l("inside obj d function")
    }
}
obj.d()
Object.defineProperty(obj, "d", { configurable: false })
delete obj.d
obj.d()
代码语言:javascript
复制
inside obj d function
inside obj d function

delete与全局作用域

当我们不使用var或者let或者const定义了一个全局作用域下的变量时, 这个变量是可变更的

代码语言:javascript
复制
f = 90;
console.log(Object.getOwnPropertyDescriptor(global, 'f'))
代码语言:javascript
复制
{ value: 90,
  writable: true,
  enumerable: true,
  configurable: true }

因此他们是可以被delete移除的.

代码语言:javascript
复制
f = 90;

console.log(f);

delete f;

console.log(f);
代码语言:javascript
复制
90

l(f)
  ^

ReferenceError: f is not defined

delete与局部作用域

delete不会影响局部作用于与函数作用域

代码语言:javascript
复制
{
    var g = 88
    delete g
}
console.log(g)
function func() {
    var funch = 90
    delete funch
    console.log(funch)
}
func()
代码语言:javascript
复制
88
90

delete与不存在的属性

如果一个本身就不存在的属性被传递给delete, 它不会抛出一个错误, 而是会返回true

代码语言:javascript
复制
var obj = {
    d: 90
}

console.log(delete obj.f);
代码语言:javascript
复制
true

delete与原型链

delete不会影响到一个对象的原型链

代码语言:javascript
复制
function Foo() {
    this.bar = 90;
}
Foo.prototype.bar = 88;

var f = new Foo();

我们创建构造器Foo, 并且在它的属性和原型链属性上都声明了一个属性bar, 它们同名但具有不同的值.

当直接引用这个对象是, Foo构造函数中定义的bar会被返回.

代码语言:javascript
复制
f.bar // 90

当我们删除了这个属性:

代码语言:javascript
复制
delete f.bar

他只会影响到Foo构造函数中定义的bar, 而不会影响到原型链中的. 当我们再次应用这个属性时, 原型链中的bar就会被返回

代码语言:javascript
复制
console.log(f.bar);
delete f.bar
console.log(f.bar);
代码语言:javascript
复制
90
88

delete与JS内建静态属性

delete操作符不能移除任何API内建的API, 包括Array, Math, Object, Date等. 对这些属性进行delete操作会的到返回值false

代码语言:javascript
复制
console.log(delete Math.PI);
代码语言:javascript
复制
false

delete与其在数列上的留洞性质(holey nature)

所有JS中的类型都继承自JSObject的C++等价定义. 每一个我们定义的对象的属性, 都是C++ JSObject的一个成员

代码语言:javascript
复制
obj = {
    d: 90,
    f: 88
}
代码语言:javascript
复制
JSObject {
    d -> 90,
    f -> 88
}

数列也属于JSObject, 只是他们之间存在一些差别. 差别在于, Array的JSObject并不是由数列自己定义的, 而是通过数字排序定义的

代码语言:javascript
复制
obj = [90, 88];
代码语言:javascript
复制
JSObject {
    0 -> 90
    1 -> 88
}

这也是为什么我们在引用数组时的方式obj[1]看起来与对象很类似的原因了. 在数组中, 这些数字就是它的属性.

在我们上述的数组中, 它有两个属性01.

类似我们对对象作出操作, 删除数组中的第一个属性(元素), 可以这么做:

代码语言:javascript
复制
delete obj[0];

console.log(obj[0]); // undefined

但是这个操作并没有减少数组中元素的个数

代码语言:javascript
复制
obj = [90, 88];
console.log(obj.length); // 2

delete obj[0];

console.log(obj.length); //2
代码语言:javascript
复制
//obj
index:  0       1
        [       ,   88];

这样就在数列中留下了孔洞

实际上在对象中, delete操作也并不是完全抹除被删除的属性, 而是将它们的值设置为undefined. 可以通过对这些属性重新赋值来填满这些被留下的孔洞

总结

我们了解delete操作符是用来干什么的, 它对可变更与不可变更属性的影响, 它对全局与局部作用域的影响, 它对数组等有洞的属性的影响.

了解这些, 你能在使用delete操作符时变得更舒服, 更谨慎.

如果有任何问题, 请随意问我, 或者发一封邮件或者DM

谢谢!!!

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • delete操作符
  • 不可变更(non-configuration)属性与delete
  • var, let, const与delete
  • delete与全局作用域
  • delete与局部作用域
  • delete与不存在的属性
  • delete与原型链
  • delete与JS内建静态属性
  • delete与其在数列上的留洞性质(holey nature)
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档