关键字“ const”不会使值不变。这是什么意思?


85

Axel Rauschmayer博士在探索ES6中const定义

const就像let一样工作,但是您声明的变量必须立即初始化,并且其值以后不能更改。[…]

const bar = 123;
bar = 456;  // TypeError: `bar` is read-only

然后他写道

陷阱:const不会使值不变

const 仅表示变量始终具有相同的值,但并不表示该值本身是不变的。

我对此陷阱感到困惑。有人可以const用这个陷阱清楚地定义吗?


38
MDN的解释是明确的:“的常量声明创建只读参照值这并不意味着其持有的值是不可变的,只是该可变标识符不能被重新分配。例如,如果内容是。对象,这意味着对象本身仍然可以更改。” (我的重点)
Gerardo Furtado

4
这意味着,如果该值是可变的(例如,如果它是一个对象),那么您仍然可以对该对象进行突变(例如,更新,添加,删除属性)。
菲利克斯·克林

2
const x = "immutable"是不可变的,因为它String是不可变的。const仅禁止重新分配。

3
@ibrahimmahrir:使一个基准(什么JavaScript并为对象)是不一样的通通过参考(其描述了绑定之间的关系,该值是不相关的)。
菲利克斯·克林

2
@ibrahimmahrir:是的,这就是问题所在。引用传递 一词具有非常具体的含义
Felix Kling

Answers:


97

MDN很好地总结了一下:

const声明创建对值的只读引用。这并不意味着它拥有的值是不变的,只是不能重新分配变量标识符。例如,如果内容是对象,则意味着对象本身仍可以更改。

更简洁地说:const创建一个不可变的绑定。

换句话说:const与var一样,为您提供了可变的内存块,您可以在其中存储一些内容。但是,const指示您必须继续引用相同的内存块–您不能将变量重新分配给不同的内存块,因为变量引用是恒定的。

要真正使某些内容在声明后保持不变且不变,您需要使用Object.freeze()。但是,这很浅,仅适用于键/值对。冻结整个对象需要花费更多的精力。以高效的方式重复执行此操作更具挑战性。如果您确实有需要,建议您检查一下Immutable.js之类的内容


20
用C表示:如果法线var x是a struct Object *x,则aconst x是a struct Object *const x。指针不能改变。它指向的东西可以。
Fund Monica的诉讼案

151

当您使用constJavaScript制作内容时,您无法将变量本身重新分配为引用其他内容。但是,该变量仍可以引用可变对象。

const x = {a: 123};

// This is not allowed.  This would reassign `x` itself to refer to a
// different object.
x = {b: 456};

// This, however, is allowed.  This would mutate the object `x` refers to,
// but `x` itself hasn't been reassigned to refer to something else.
x.a = 456;

对于诸如字符串和数字之类的基元而言,const它更易于理解,因为您无需更改值,而是为变量分配了新值。


18
这个答案比公认的要好得多。更为简洁,并包含实际的示例代码。(换句话说,到了重点。)+1
jpmc26

16

重新绑定

constlet声明控制是否允许在标识符和值之间进行重新绑定(也称为重新分配):

const x = "initial value";
let y = "initial value";

// rebinding/reassignment

try { x = "reassignment" } catch(e) { console.log(x) } // fails

y = "reassignment"; // succeeds
console.log(y);

不变性

不变性在类型级别上进行控制。Object是可变类型,而是String不可变类型:

const o = {mutable: true};
const x = "immutable";

// mutations

o.foo = true; // succeeds
x[0] = "I"; // fails

console.log(o); // {mutable: true, foo: true}
console.log(x); // immutable


1

const的意思是:您不能更改初始分配的值。

首先,定义什么是js中的。值可以是:布尔值,字符串,数字,对象,函数和未定义的值。

就像:人们用你的名字呼唤你,它没有改变。但是,您要换衣服。结合和人民之间,你是你的名字。其余的可以改变。对不起,这个奇怪的例子。

所以,让我给你一些例子:

// boolean
const isItOn = true;
isItOn = false;           // error

// number
const counter = 0;
counter++;                // error

// string
const name = 'edison';
name = 'tesla';           // error

// objects
const fullname = {
  name: 'albert',
  lastname: 'einstein'
};

fullname = {              // error
  name: 'werner',
  lastname: 'heisenberg'
};
// NOW LOOK AT THIS:
//
// works because, you didn't change the "value" of fullname
// you changed the value inside of it!
fullname.name = 'hermann';

const increase = aNumber => ++aNumber;
increase = aNumber => aNumber + 1;      // error

// NOW LOOK AT THIS:
//
// no error because now you're not changing the value
// which is the decrease function itself. function is a
// value too.
let anotherNumber = 3;
const decrease = () => --anotherNumber;

anotherNumber = 10;             // no error
decrease();                     // outputs 9

const chaos = undefined;
chaos = 'let there be light'    // error

const weird = NaN;
weird = 0                       // error

如您所见,除非您没有将“第一个”赋值更改为const,否则没有错误。每当您尝试将第一个分配的值更改为其他值时,它都会生气,并且会产生错误。

因此,这是您在使用时可能会知道的第二件事const。也就是说,应该在声明时将其初始化为一个值,否则会很生气。

const orphan;                    // error
const rich = 0;                  // no error

0

ES6/ES2015 const关键字:

所述const关键字被用于声明的块范围的变量(如使用声明let)。使用const和声明变量之间的区别let如下:

  1. 声明的变量 const不能重新分配
  2. 与声明的变量const必须分配宣布。这是上一点的逻辑结果,因为const不能重新分配用声明的变量,这就是为什么在声明变量时必须将其精确分配一次

例:

// we declare variable myVariable
let myVariable;

// first assignment
myVariable = 'First assingment';
// additional assignment
myVariable = 'Second assignment';

// we have to declare AND initialize the variable at the same time
const myConstant = 3.14;

// This will throw an error
myConstant = 12;

在上面的示例中,我们可以观察到以下内容:

  1. 可以先myVariable声明用声明的变量let,然后再赋值。
  2. myConstant声明的变量const必须同时声明和分配。
  3. 当我们尝试重新分配变量时myConstant,出现以下错误:

未捕获的TypeError:分配给常数变量

警告:分配给的变量const仍然是可变的:

用Just声明的变量const不能被重新分配,它仍然是mutable。可变的意味着分配给const变量的数据结构(对象,数组,地图等)仍然可以更改(即变异)。突变的例子有:

  1. 添加/删除/更改对象的属性
  2. 在特定的数组索引处更改数组的值

如果确实希望对象不可变,您将必须使用类似的东西Object.freeze()。这是一种冻结对象的方法。冻结的对象无法再更改,并且不能添加任何新属性。

例:

const obj = {prop1: 1};

obj.prop1 = 2;
obj.prop2 = 2;

console.log(obj);

// We freeze the object here
Object.freeze(obj);

obj.prop1 = 5;
delete obj.prop2;

// The object was frozen and thus not mutated
console.log(obj);

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.