谈谈const跟Object.freeze()

时间:2022-07-25
本文章向大家介绍谈谈const跟Object.freeze(),主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

自发布以来,ES6为JavaScript带来了一些新特性和方法。这些新特性可以极大地改善我们开发人员的编码方式,提高生产力。今天我们来聊聊Object.freeze()方法和const

有人认为这两个新特性在功能上重复了,其实不然。Object.freeze()const的使用场景是有区别的,听我慢慢道来。

先来看看字面上的区别:

  • const表现像let。唯一的区别是,它定义的变量无法再次赋值。const声明的变量具有块级作用域。它偏向于变量指向的内存地址不可变。
  • Object.freeze()将一个对象作为参数,返回同一个对象的immutable版本。这意味着我们希望不能添加,删除或更改此对象的任何属性。它偏向于对象不可变。

mutable对象具有可以更改的属性。immutable对象创建后便不可以更改属性。

可能光说内存地址不可变跟对象不可变还是有点抽象哈,我们来看几块代码就明白了。

来看个例子:

const

const user = 'zong'
user = 'jacob'

我们试图给使用const关键字声明的变量user重新赋值,但这是一个无效的操作,会抛出一个Uncaught TypeError异常。

只有varlet声明的变量才能重新赋值。

const的问题

当声明对象时,使用const仅防止再次赋值,但不保证不可变性(immutable),也就是不能防止更改其属性的值。

const仅仅只能保证

const user = {
  name: 'xxx'
}// won't work

我们无法对这个变量再次赋值。

但是我们可以修改这个对象本身,比如下面这段代码:

const user = {
  name: 'zong',
  email: 'hizong@xxx.com',
  country: 'China',
}
user.last_name = 'jacob';

但这有时候并不是我们想要的,我们不希望我们的对象被修改,这时候 Object.freeze()就派上用场了。

Object.freeze()

为了禁止对对象进行修改,我们需要使用 Object.freeze()

const user = {
  name: 'zong',
  email: 'hizong@xxx.com',
  country: 'China',
}
Object.freeze(user)
user.name='xxx' //won't work
console.log(user)

Object.freeze()的问题

1.它是一个浅操作

要注意的是, Object.freeze()是一个浅操作, 如果user某个属性是一个对象,那我们是需要递归地去应用它来确保整个user对象是不可修改的。

const user = {
  name: 'zong',
  contact: {
    email: 'hi@xxx.com',
    mobile: 000000,
  }
} 
Object.freeze(user);
user.name= 'jacob' //won't work
user.contact.telephone = 111111  //work
console.log(user)

所以当一个对象某个属性也是一个对象时,Object.freeze()并没有完全freeze 一个对象。

要完全让一个对象不可变,我们得自己递归处理或者使用Deepfreeze或immutable-js这样的库。

2. 我们还可以对变量重新赋值

Object.freeze()仅仅让传入它的对象immutable,让我们无法修改它的属性,但是它没有规定我们不能修改变量指向的对象,也就是我们可以给变量重新赋值。

let user = {
  name: 'zong',
  contact: {
    email: 'hi@xxx.com',
    mobile: 000000,
  }
} 
Object.freeze(user);
console.log(user)
user={
    name:'xxx'
}
console.log(user)

我们可以看到,如果我们用let去声明了一个变量,尽管经过Object.freeze()处理后,它指向的对象属性不可修改,但我们仍可以重新赋值。如果是const声明的变量,那就不行了。

到这儿我们就彻底搞清楚它们的区别啦,const侧重于变量指向的内存地址不可变,Object.freeze()侧重于生成的对象属性不可变。两者结合有可能实现一个内存地址,属性都不可变的对象。