172

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

在规范中,它写道:

常量的值不能通过重新赋值来改变,也不能重新声明常量。因此,虽然可以在不初始化的情况下声明一个常量,但这样做是没有用的。

当我做这样的事情时:

const xxx = 6;
xxx = 999;
xxx++;
const yyy = [];
yyy = 'string';
yyy = [15, 'a'];

我看到一切都很好,xxx仍然是。6yyy[]

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

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

4

11 回答 11

255

该文档指出:

...常数不能通过重新分配来改变
...常数不能重新声明

当您添加到数组或对象时,您并没有重新分配或重新声明常量,它已经被声明和分配,您只是添加到常量指向的“列表”中。

所以这很好用:

const x = {};

x.foo = 'bar';

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

x.foo = 'bar2';

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

和这个:

const y = [];

y.push('foo');

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

y.unshift("foo2");

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

y.pop();

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

但这些都不是:

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
于 2014-05-02T20:38:29.037 回答
71

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

如果你想冻结一个数组或对象使其不能被修改,你可以使用该Object.freeze方法,它已经是 ECMAScript 5 的一部分。

const x = Object.freeze(['a'])
x.push('b')
console.log(x) // ["a"]
于 2014-05-02T20:42:24.177 回答
16

这与我能想到的每一种编程语言都是一致的。

考虑 C - 数组只是美化的指针。一个常量数组只意味着指针的值不会改变——但实际上包含在该地址的数据是自由的。

在 javascript 中,您可以调用常量对象的方法(当然——否则常量对象将没有多大用处!)这些方法可能具有修改对象的副作用。由于 javascript 中的数组是对象,因此这种行为也适用于它们。

您可以放心的是,常量将始终指向同一个对象。对象本身的属性可以自由更改。

于 2014-05-02T20:55:07.170 回答
16

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

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

const number = {
    id:5,
    name:'Bob'
};

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

number.name = 'John';

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

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

TypeError: Assignment to constant variable.
于 2019-06-17T17:15:22.640 回答
6

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

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

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

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

于 2018-08-09T20:37:59.680 回答
4

关键字 const 有点误导。

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

因此,您不能:

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

但是你可以:

  • 改变一个常量数组
  • 改变一个常量对象
于 2021-08-01T09:56:27.593 回答
4

const 声明创建对值的只读引用。这并不意味着它持有的值是不可变的,只是不能重新分配变量标识符。例如,在内容是对象的情况下,这意味着可以更改对象的内容(例如,它的参数)。

此外,还有一个重要的注意事项:

全局常量不会成为窗口对象的属性...

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const

于 2018-04-23T12:14:45.373 回答
1

const 的值不能通过重新赋值来改变,也不能重新声明。

const testData = { name:"Sandeep",lastName:"Mukherjee",company:"XYZ"}

第一个案例

testData = {name:"hello"}
console.log(testData);//throws an Error:Assignment to constant variable
Here we are reassigning testData again

第二种情况

const testData = {name:"Sandeep",lastName:"Mukherjee",company:"ABC"}
console.log(testData); //throws an Error: Identifier 'testData' has already been declared
Here we are redeclaring testData again

当使用 const 声明变量时,这意味着它指向某个内存位置 const 的行为是我们可以操作存储在该内存位置但不能操作内存位置的值,当我们重新分配/重新声明它不允许更改的 const 变量时内存位置

我们可以改变特定键的值

testData.company = "Google"
 console.log(testData);
 //{ name: 'Sandeep', lastName: 'Mukherjee', company: 'Google' }

我们可以向它添加任何新的键值对

 testData.homeTown = "NewYork"
 console.log(testData)
 //{name: 'Sandeep',lastName:'Mukherjee',company:'Google',homeTown: 'NewYork'}
于 2021-10-30T08:20:30.903 回答
0

const 变量存储的地址(内存地址如 0xFF2DFC)是常数。

常量不是内存中的内容。

常量只是内存地址

感谢您的阅读。

于 2020-12-26T03:35:29.500 回答
0

const MY_OBJECT = {'key': 'value'};

// 尝试覆盖对象会引发错误 // Uncaught TypeError: Assignment to constant variable。 MY_OBJECT = {'OTHER_KEY': 'value'};

// 但是,对象键不受保护, // 所以下面的语句执行没有问题 MY_OBJECT.key = 'otherValue'; // 使用 Object.freeze() 使对象不可变

// 这同样适用于数组 const MY_ARRAY = []; // 可以将项目推入数组 MY_ARRAY.push('A');// ["A"] // 但是,将新数组分配给变量会引发错误 // 未捕获的类型错误:分配给常量变量。 MY_ARRAY = ['B'];

于 2021-06-27T17:58:21.067 回答
0

因为在 const 中您可以更改对象的值,所以该对象实际上并不存储分配数据,而是指向它。所以 Javascript 中的原语和对象是有区别的。

于 2020-01-16T12:58:09.010 回答