在JavaScript中,为什么常量字符串不能被修改,但常量数组可以被修改?

4
const name = 1;
name = 2;

执行此 JavaScript 时出现错误:
TypeError: Assignment to constant variable.
    at Object.<anonymous> (/home/user01/JavaScript/scope.js:2:6)
    at Module._compile (module.js:652:30)
    at Object.Module._extensions..js (module.js:663:10)
    at Module.load (module.js:565:32)
    at tryModuleLoad (module.js:505:12)
    at Function.Module._load (module.js:497:3)
    at Function.Module.runMain (module.js:693:10)
    at startup (bootstrap_node.js:191:16)
    at bootstrap_node.js:612:3

但是,执行以下语句时,代码可以成功执行。

const arr = [1,2,3];
arr[1] = 5;

为什么即使声明为常量,我们也能修改数组?

很不幸,const并不意味着“不可变”。 - E net4
2
这是因为常量无法被重新分配。当您更改数组时,您并未重新分配变量。如果您不希望arr是可变的,您可以使用Object.freeze(arr) - Mark
2个回答

6
由于数组本身没有改变,它仍然是同一个数组。在类C语言中,其类似的相应物是一个常量指针(指向内存中的某个地址)——您不能更改指针指向的位置,但内存是可以写入的。
在JavaScript中,这种指针般的行为适用于任何不是基本类型(即NumberBooleanString...)的东西,这基本上包括数组和对象。如果您想知道为什么String是基本类型,请参阅JavaScript字符串是不可变的

3

ES2015中的const并不表示一个值是constant或者immutable(不可变的)。const值肯定是可以改变的。下面是一个完全有效的ES2015代码,它不会抛出异常:

const obj = {};
obj.bar = 42;
console.log(obj.bar);
// → 42

const arr = [1, 2, 3];
arr[1] = 42;
console.log(arr[1]);
// → 42

这里唯一不变的是绑定(binding)。const 将一个值 ({}) 赋给一个变量名 (obj),或将一个值 ([]) 赋给一个变量名 (arr),并保证不会再次绑定。在 const 变量上使用 赋值操作符 或者 一元后缀 --++ 操作符,都会抛出 TypeError 异常
因此,下面任何一行都会抛出异常。
const foo = 27;
foo = 42;
foo *= 42;
foo /= 42;
foo %= 42;
foo += 42;
foo -= 42;

现在的问题是如何使变量 immutable

原始值,即数字字符串布尔值符号nullundefined都是不可变的。

var foo = 27;
foo.bar = 42;
console.log(foo.bar);
// → `undefined`

要让一个对象的值变为不可变的,可以使用 Object.freeze() 方法。它从ES5开始就存在,并且现在已经得到了广泛的应用。

const foo = Object.freeze({
    'bar': 27
});
foo.bar = 42; // throws a TypeError exception in strict mode;
              // silently fails in sloppy mode
console.log(foo.bar);
// → 2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接