为什么我可以在javascript中更改常量的值

Sal*_*ali 80 javascript const ecmascript-6

我知道ES6还没有标准化,但是很多浏览器目前都支持 const JS中的关键字.

在规范中,它写道:

常量的值不能通过重新赋值来改变,并且不能重新声明常量.因此,尽管可以在不初始化的情况下声明常量,但这样做是没用的.

当我做这样的事情时:

const xxx = 6;
xxx = 999;
xxx++;
const yyy = [];
yyy = 'string';
yyy = [15, 'a'];
Run Code Online (Sandbox Code Playgroud)

我看到一切正常xxx6yyy[].

但是,如果我这样做yyy.push(6); yyy.push(1);,我的常数阵列已被改变.现在它是[6, 1],顺便说一句,我仍然无法改变它yyy = 1;.

我这是一个错误,还是我错过了什么?我用最新的chrome和FF29试了一下

ade*_*neo 139

文件说明:

...常量不能通过重新赋值改变
...常量不能重新声明

当您添加到数组或对象时,您没有重新分配或重新声明常量,它已经被声明和分配,您只需添加常量所指向的"列表".

所以这很好

const x = {};

x.foo = 'bar';

console.log(x); // {foo : 'bar'}

x.foo = 'bar2';

console.log(x); // {foo : 'bar2'}  
Run Code Online (Sandbox Code Playgroud)

还有这个

const y = [];

y.push('foo');

console.log(y); // ['foo']

y.unshift("foo2");

console.log(y); // ['foo2', 'foo']

y.pop();

console.log(y); // ['foo2']
Run Code Online (Sandbox Code Playgroud)

但这些都不是

const x = {};
x = {foo: 'bar'}; // error - re-assigning

const y = ['foo'];
const y = ['bar']; // error - re-declaring

const foo = 'bar'; 
foo = 'bar2';       // error - can not re-assign
var foo = 'bar3';   // error - already declared
function foo() {};  // error - already declared
Run Code Online (Sandbox Code Playgroud)

  • @SalvadorDali:*常量*和*只读*是两个不同的东西.你的变量是*常量*,但它所指向的数组不是*只读* (19认同)
  • 是的,应该以这种方式工作,您不必重新分配常量,它仍然是相同的引用,您只是将常量引用添加到数组中,而数组和对象就像“列表”一样,对其进行修改请勿更改引用或重新声明常量。 (4认同)
  • 所以您的意思是这不是错误,但是应该可以这样工作吗?因为我认为常量的想法是不能更改。基本上,程序员相信无论发生什么事情,任何事情都不能改变我的常量内部的值。 (2认同)
  • 我认为这并不容易,在这种情况下,常量的值是特定元素的数组。改变任何东西都意味着你改变了*值*。 (2认同)
  • 所以基本上变量是一个指针,作为“const”,你不能改变它引用或指向的内存地址,但你可以自由地改变内存地址保存的值? (2认同)

Gui*_*ehn 34

发生这种情况是因为您的常量实际上存储了数组的引用.当您将某些内容加入到数组中时,您不会修改常量值,而是指向它所指向的数组.如果将对象分配给常量并尝试修改它的任何属性,也会发生同样的情况.

如果要冻结数组或对象以使其无法修改,则可以使用该Object.freeze方法,该方法已经是ECMAScript 5的一部分.

const x = Object.freeze(['a'])
x.push('b')
console.log(x) // ["a"]
Run Code Online (Sandbox Code Playgroud)

  • 按照同样的逻辑,设置为 5 的常量“五”实际上并不具有值 5,它只是对数字 5 的引用。因此,如果我执行“五++”,我不会更改常量,只是更改它指向的编号。 (2认同)
  • @Anthony参考对象仅适用于数组和对象,不适用于原始值 (2认同)
  • @Anthony 在您的示例中,您正在更改变量 `five` 指向的数字(变量 `five` 曾经是数字 5 的标签,现在它指向不同的数字:6)。在问题(和这个答案)的例子中,`x` 总是指向同一个列表;如果 `x` 是 const 你不能让它指向不同的列表。唯一的区别是同一个列表可以增长或缩小;这仅适用于数组和对象,而不适用于基元。 (2认同)

小智 10

关键字 const 有点误导。

它没有定义常量值。它定义了对值的常量引用。

因此,您不能:

  • 重新分配一个常量值
  • 重新分配常量数组
  • 重新分配常量对象

但是你可以:

  • 更改常量数组
  • 改变一个常量对象


tho*_*day 6

这是我能想到的每种编程语言的一致行为.

考虑C - 数组只是美化指针.常量数组仅表示指针的值不会改变 - 但实际上该地址包含的数据是免费的.

在javascript中,您可以调用常量对象的方法(当然 - 否则常量对象不会起到太多作用!)这些方法可能具有修改对象的副作用.由于javascript中的数组是对象,因此这种行为也适用于它们.

你可以确定的是,常量总是指向同一个对象.对象本身的属性可以自由更改.


Atu*_*lic 6

在搜索为什么即使将对象定义为const. 所以这里的重点是它不是直接的对象,而是它包含的可以更新的属性。

例如,我的对象看起来像:

const number = {
    id:5,
    name:'Bob'
};
Run Code Online (Sandbox Code Playgroud)

上面的答案正确地指出它是常量而不是它的属性的对象。因此,我将能够通过执行以下操作来更新 ID 或名称:

number.name = 'John';
Run Code Online (Sandbox Code Playgroud)

但是,我将无法像这样更新对象本身:

number = {
    id:5,
    name:'John'
  };

TypeError: Assignment to constant variable.
Run Code Online (Sandbox Code Playgroud)

  • 你的例子是一个实用的例子并且描述正确 (2认同)

Zyx*_*xmn 5

我认为这会让你更清楚这个问题:https : //codeburst.io/explaining-value-vs-reference-in-javascript-647a975e12a0

基本上它归结为const始终指向内存中的相同地址。您可以更改存储在该地址中的值,但也不能更改const指向的地址。

constconst指向包含原始值的地址时,您提到的定义将成立。这是因为您不能在const不更改其地址的情况下为其分配值(因为这是分配原始值的工作方式)并且const不允许更改 a 的地址。

如果const指向非原始值,则可以编辑地址的值。