为什么我可以在 javascript 中改变一个常量对象

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

具体来说,书中写道:

常数的值不能通过重新赋值来更改,而且 常量不能重新声明。因此,尽管它是 如果可以在不初始化常数的情况下声明常数,则 这样做是没有用的

当我这么做的时候:

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;

这是一个错误,还是我遗漏了什么? 我试过在最新的铬和 FF29

132126 次浏览

文件中写道:

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

当你添加到一个数组或对象时,你没有重新赋值或重新声明常量,它已经被声明和赋值了,你只是添加到常量指向的“列表”中。

因此,这种方法很有效:

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

之所以会发生这种情况,是因为常量实际上将 参考文献存储到数组中。当您将某些内容加入到数组中时,您并没有修改常量值,而是修改它所指向的数组。如果将一个对象赋给一个常量并试图修改它的任何属性,也会发生同样的情况。

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

const x = Object.freeze(['a'])
x.push('b')
console.log(x) // ["a"]

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

考虑到 C 数组只是被美化的指针。常量数组只意味着指针的值不会改变——但事实上该地址中包含的数据可以自由访问。

在 javascript 中,允许调用常量对象的方法(当然,否则常量对象就没什么用了!)这些方法可能会产生修改对象的副作用。因为 javascript 中的数组是对象,所以这种行为也适用于它们。

你所能确定的就是这个常量总是指向同一个对象。对象本身的属性可以自由更改。

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

此外,还有一点很重要:

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

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

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

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

const指向一个包含基元值的地址时,您提到的 const的定义将为 true。这是因为您不能在不更改其地址的情况下为该 const赋值(因为这是赋基元值的工作方式) ,并且不允许更改 const的地址。

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

通过这篇文章,当搜索为什么我能够更新一个对象,即使它定义为 const。因此,这里的要点是,它不是直接的对象,而是它包含的属性,可以更新。

例如,my Object 看起来像:

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

上面的回答正确地指出了 Object 是 const,而不是它的属性。因此,我可以通过以下方法更新 id 或名称:

number.name = 'John';

但是,我不能像这样更新对象本身:

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


TypeError: Assignment to constant variable.
因为通常你可以改变一个对象的值,所以这个对象实际上并不存储赋值数据,而是指向赋值数据。 所以在 Javascript 中,原语和对象是有区别的

Const 变量存储常量的地址(内存地址,如0xFF2DFC)。

常量不是内存中的内容。

常量是内存地址 ONLY

谢谢你的阅读。

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

尝试覆盖对象将抛出一个错误 //未捕获的 TypeError: 赋值给常量变量。 MY_OBJECT = {'OTHER_KEY': 'value'};

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

< p >//这同样适用于数组 const MY_ARRAY = []; //可以将项目推入数组 MY_ARRAY.push('A');//[“ A”] //但是,为变量指定一个新数组将引发错误 //未捕获的 TypeError: 赋值给常量变量。 MY_ARRAY = ['B'];

关键字 const 有点误导人。

它不定义常量值,而是定义对值的常量引用。

正因为如此,你不能:

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

但是你可以:

  • 更改常量数组
  • 更改常量对象

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 变量时 不允许更改内存位置

我们可以更改特定键的值

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'}

在您的常量中保存的不是对象,而是链接到对象。

你不能改变这个链接,因为它是常量。 但是你可以改变对象