ES6的const并非一定为常量
摘要: const定义的变量一定为常量吗?No!
- 原文:ES2015 const is not about immutability
- 作者: Mathias Bynens: Google V8引擎开发者
- 译者:Fundebug
对于ES6的const变量,大家一直存在误会,这篇博客将试着解开真相。
const的本质
const定义的变量并非常量,并非不可变。使用const定义的对象或者数组,其实是可变的。下面的代码并不会报错:
const foo = {}; |
为什么会这样?下面引用大神阮一峰的ECMAScript 6 入门
const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。但对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指向实际数据的指针,const只能保证这个指针是固定的(即总是指向另一个固定的地址),至于它指向的数据结构是不是可变的,就完全不能控制了。因此,将一个对象声明为常量必须非常小心。
因此,当我们使用赋值运算符, 一元运算符以及后缀运算符对const变量进行修改时,会出现“TypeError:Assignment to constant variable”报错:
const foo = 27; |
如果你需要监控线上应用的BUG的话,欢迎免费试用Fundebug。
如何定义常量?
对于数值、字符串和布尔值变量,使用const定义的话是不可变的:
const name = "Fundebug"; |
使用Object.freeze()可以让对象不可变,这个API从ES5开始就有了。
const foo = Object.freeze( |
注意,Object.freeze()是有局限性的,对象中嵌套对象仍然可以被修改。MDN提供了一下deepFreeze示例代码,是利用Object.freeze()实现的,可以让嵌套对象也不可变。
另外,Object.freeze()仅对键值对有效。对于Date, Map和Set,目前还没有相应方法。因此有人提议在ECMAScript标准中添加不可变的Map和Set等数据类型。
const和let如何选择?
const和let的唯一区别在于,const可以让数值、字符串和布尔变量不可变。
以上所说的内容都是事实,下面我想表达一下自己的观点。
const可以提高代码的可读性,因为const定义的数值、字符串和布尔变量是不可变的,而const定义的对象始终指向同一个对象。而使用let时,不能保证这些。因此,对于let和const,我们应该这样选择:
- 默认使用const
- 仅当变量需要修改时使用let
- 不要使用var
你是否同意我的观点呢?欢迎大家交流讨论~
参考
关于Fundebug
Fundebug专注于JavaScript、微信小程序、微信小游戏、支付宝小程序、React Native、Node.js和Java线上应用实时BUG监控。 自从2016年双十一正式上线,Fundebug累计处理了30亿+错误事件,付费客户有阳光保险、达令家、核桃编程、荔枝FM、微脉等众多品牌企业。欢迎大家免费试用!
版权声明: 转载时请注明作者KiwenLau以及本文地址: https://kiwenlau.com/2018/07/25/es6-const/