Logo
Published on

【译】JavaScript中Object.freeze()和const的区别

Authors

ES6的发布带来了很多新的特性和方法。这些特性帮助JavaScript的开发者们显著地提高了他们的开发流程和生产力。Object.freeze()方法和const体现得最明显。

在一部分开发者之中,尤其是新手,他们会争论说这两个特性没有区别,但其实不是这样的。Object.freeze()和const其实很有区别。让我们一起来看看吧。

概览

const和Object.freeze()是完全不同的。

const的行为和let类似。它们俩唯一的区别是,前者定义了一个不能重新赋值的变量。使用const定义的变量是有块级作用域的并且不像var定义的变量那样有函数级作用域。

Object.freeze()接受一个对象作为参数,同时返回一个不能被修改的和参数一样的对象。这也就是说,不能对对象的属性做添加、删除、修改的操作。

可变对象的属性是可以被修改的。不可变对象在被创建之后,所有属性都不能被修改。

例子

Const

const user = 'Henry'

user = 'YANG'

这会抛出一个Uncaught TypeError,因为我们尝试修改一个用const定义的变量重新赋值。这是不合法的。而类似的操作应该是用var或者let定义变量,而不是用const。

Const的问题

当使用const声明对象时,这只能保障这个变量不被重新赋值,而不能保证它是不可变的。

考虑以下代码。我们用const声明了一个变量叫做user并且给它赋值了一个对象。

const user = {
  first_name: 'Henry',
  last_name: 'YANG',
  email: 'sephenry@gmail.com',
  age: 18,
}

user.last_name = 'WANG'
// 这是正常的,因为user仍是一个可变的变量

user.age = 30
// 这也是正常的,而且,user长大了。。。

虽然我们不能给这个变量重新赋值,但是我们可以修改这个对象的内容。

const user = {
  user_name: 'Emma Waston',
}
// 这样就会报错了

我们肯定是希望这个对象的属性是不能被修改或删除的。const是做不到的,而Object.freeze()是可以的。

看看Object.freeze()

它可以拒绝我们对对象做的任何操作:

const user = {
    first_name: 'Henry',
    last_name: 'YANG',
    email: 'sephenry@gmail.com`,
    age: 18
}

Object.freeze(user)

user.last_name = 'WANG'
// 这样是不行的,user现在是不可变的了

嵌套的对象的属性并不能被冻结

好吧,Object.freeze()也有它自己的不足,如果有嵌套的对象,你需要自己对嵌套的内容再应用Object.freeze()。

const user = {
  first_name: 'Henry',
  last_name: 'YANG',
  contact: {
    email: 'sephenry@gmail.com',
    telephone: 008688888888,
  },
}

Object.freeze(user)

user.last_name = 'WANG'
// 这个操作是不被允许的

user.contact.teleplhone = 114
// 这个操作是生效的,因为嵌套的对象不会被冻结

所以,Object.freeze()并不会完全冻结一个对象中的嵌套对象。

如果想对嵌套的对象也冻结,我们可以写适合自己的库函数或者使用一些成熟的库,例如:Deepfreeze或者immutable-js

小结一下

const和Object.freeze()是不同的,const防止变量被重新定义和赋值,而Object.freeze()使对象不可变。