关于 const 的讲解,网络上有一大堆内容。这里摘一下 MDN 对它的介绍:
The value of a constant can't be changed through reassignment (i.e. by using the assignment operator), and it can't be redeclared (i.e. through a variable declaration). However, if a constant is an object or array its properties or items can be updated or removed.
可以看出 const 不能重新赋值,也不能重新定义。但是 const 对象(或数组)内部的属性(或元素)可以被修改。上面的文字算是个冠冕堂皇的介绍,下面我将开始对它实践操作。
demo 1
const a = 1
function foo() {
a = 2
}
foo()
在函数调用中修改其值,结果非常明显:
demo 2
const a = 1
function foo(a) {
a = 2
}
foo(a)
console.log(a)
将 const 值作为参数传入函数中,函数能否对其修改?输出 1、2,还是报错?延伸一下这个例子,下面的代码输出什么:
const a = {b: 1}
function foo(a) {
a = {b: 2}
}
foo(a)
console.log(a)
也许上段代码你会有一分不确定,但下面这个例子的结果想必你可以 100% 肯定:
// 堆代码 duidaima.com
const a = {b: 1}
function foo(a) {
a.b = 2
}
foo(a)
console.log(a)
demo 3
const a = 1
const b = { a }
function foo(b) {
b.a = 2
}
foo(b)
console.log(a, b)
const 值作为一个对象的属性时,我们可以改变它吗?会报错吗?如果不报错,a 和 b 分别是多少?
答案
demo 2 的答案是 1 ,延伸问题为 {b: 1}。
demo 3 的答案是 a 为 1,b 为 {a: 2} 。
理解上面的 demo 还需要一个额外的知识:当进行函数调用时,JavaScript 会通过“值传递”的方式进行,因此调用函数内部是新的栈值,不受保护。也许你听过“引用传递”的说法,事实上这种说辞可能让你的理解更混乱,所谓“引用传递”只是因为原来的栈值里是一个内存地址(虚拟内存地址)而已,调用函数时传入的仍然是一份复制后的值,不区分基础类型(如数字)或引用。
以 demo2 为例子:

demo2 的延伸为:

结论很明显:JavaScript 的 const 只保护当前变量栈值不被修改。 这应该是解释器运行期的一种保护策略,故而其实用价值不大,毕竟对于不存在编译期的 JavaScript,这一特性只能让我们调试时更容易发现程序的BUG 而已,而我们也看到,它并不能让我们将某变量理想地“约定”为只读,相比之下它甚至不如 Object.freeze 实用。也许这也是我接触的大多数 JavaScript 程序员并不怎么真正使用 const 的原因。