如何const定义一个不可变数组

有个常见的面试题,我们知道,const是es6中新增用于定义常量。但是对于引用类型来说,const 所说的常量,是指,对应的指针或者说地址是常量。那么,如果我们要求,我们定义的数组里面的元素也是不可改变的呢?先来看现象

const a = [1, 2, 3];
console.log(a);
a[0] = 4;
console.log(a)
复制代码

输出是

[1, 2, 3]
[4, 2, 3]
复制代码

可以简单,用const定义的数组,里面的元素是可变的

那么,考虑到,数组其实也是继承于对象,那么,根据下面三个规则

  1. Object.preventExtendsion(obj) 用来禁止对象可扩展其它属性
  2. Object.seal(obj)用来禁止对象删除其它属性和扩展其它属性
  3. Object.freeze(obj)用来冻结对象,就是所有的属性不能够更改和新增

关于Object.preventExtendsion

来看第一种方案

const a = [1, 2, 3, {second: 11}];
console.log(a);
console.log(Object.getOwnPropertyDescriptor(a, 0));
Object.preventExtensions(a); // 开始锁定对象
a[4] = 4;
console.log(a)
console.log(Object.getOwnPropertyDescriptor(a, '1'));
console.log(Object.isExtensible(a));
delete a[0];
console.log(a);
复制代码

输出如下:

[1, 2, 3, [object Object] {
  second: 11
}]
[object Object] {
  configurable: true,
  enumerable: true,
  value: 1,
  writable: true
}
[1, 2, 3, [object Object] {
  second: 11
}]
[object Object] {
  configurable: true,
  enumerable: true,
  value: 2,
  writable: true
}
false
[undefined, 2, 3, [object Object] {
  second: 11
}]
复制代码

由此可见,preventExtensions可以阻止对象新增属性。但是原对象依旧可以改删其它原有属性,

关于object.seal

const a = [1, 2, 3, {second: 11}];
console.log(a);
console.log(Object.getOwnPropertyDescriptor(a, 0));
Object.seal(a);
a[4] = 4;
console.log(a);
console.log(Object.getOwnPropertyDescriptor(a, '1'));
console.log(Object.isExtensible(a));
delete a[0];
console.log(a);
a[0] = 5;
console.log(a);
复制代码

输出如下:

[1, 2, 3, [object Object] {
  second: 11
}]
[object Object] {
  configurable: true,
  enumerable: true,
  value: 1,
  writable: true
}
[1, 2, 3, [object Object] {
  second: 11
}]
[object Object] {
  configurable: false,
  enumerable: true,
  value: 2,
  writable: true
}
false
[1, 2, 3, [object Object] {
  second: 11
}]
[1, 2, 3, [object Object] {
  second: 11
}]
复制代码

可以看到,configurable已经变成了false,说明是不可以删除的,后面的delete操作也是无效。但是,对象里面的值却是可以更改的

关于Object.freeze

所以,有了以下方案:

const a = [1, 2, 3];
console.log(a);
Object.freeze(a);
a[0] = 4;
console.log(a)
复制代码

输出如下

[1, 2, 3]
[1, 2, 3]
复制代码

由此可见,对象里面的元素也是不可变的

再来试验,如果对应的value不是个简单数据类型呢,比如如下

const a = [1, 2, 3, {second: 11}];
console.log(a);
console.log(Object.getOwnPropertyDescriptor(a, 0));
Object.freeze(a);
a[4] = 4;
console.log(a);
console.log(Object.getOwnPropertyDescriptor(a, '1'));
console.log(Object.isExtensible(a));
delete a[0];
console.log(a);
复制代码

输出如下


[1, 2, 3, [object Object] {
  second: 11
}]
[object Object] {
  configurable: true,
  enumerable: true,
  value: 1,
  writable: true
}
[1, 2, 3, [object Object] {
  second: 11
}]
[object Object] {
  configurable: false,
  enumerable: true,
  value: 2,
  writable: false
}
false
[1, 2, 3, [object Object] {
  second: 11
}]
复制代码

证明,还是不可变的

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值