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

时间:2017-03-16 12:02:07

标签: javascript ecmascript-6 const

Axel Rauschmayer博士在探索ES6 中有const definition

  

const就像let一样,但你声明的变量必须是   立即初始化,具有无法更改的值   之后即可。 [...]

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

然后他写了

  

Pitfall: const does not make the value immutable

     

const仅表示变量始终具有相同的值,   但这并不意味着价值本身就是不可变的。

我对这个陷阱感到困惑。任何人都可以清楚地定义const这个陷阱吗?

5 个答案:

答案 0 :(得分:149)

当您在JavaScript中创建const内容时,您无法重新分配变量本身以引用其他内容。但是,变量仍然可以引用可变对象。

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更容易理解,因为您不会改变值,而是为变量赋值。

答案 1 :(得分:96)

MDN总结得很好:

  

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

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

换句话说:const,就像var一样,为你提供了一个可变的内存块,你可以在其中存储一些东西。但是,const指示你必须继续引用同一块内存 - 你不能将变量重新分配给不同的内存块,因为变量引用是常量。

要在声明之后真正使某些东西保持不变且不变,你需要使用像Object.freeze()这样的东西。但是,这很浅,仅适用于键/值对。冻结整个对象需要更多的努力。以高效的方式反复这样做更具挑战性。如果您确实需要,我建议您查看Immutable.js

之类的内容

答案 2 :(得分:14)

重绑定

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

答案 3 :(得分: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

答案 4 :(得分:0)

ES6 / ES2015 const关键字:

const关键字用于声明块作用域变量(如使用let声明)。用constlet声明变量之间的区别如下:

  1. 声明为const的变量不能重新分配
  2. 用<{1}声明的变量必须在声明时进行分配。这是前一点的逻辑结果,因为无法重新分配用const声明的变量,这就是为什么在声明该变量时必须将其精确赋值一次

示例:

const

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

  1. // 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;声明的变量myVariable可以先声明然后再赋值。
  2. let声明的变量myConstant必须同时声明和分配。
  3. 当我们尝试重新分配变量const时,出现以下错误:
  

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

注意:分配给myConstant的变量仍然是可变的:

const声明的变量无法重新分配,它仍然是可变的。可变是指分配给const变量的数据结构(对象,数组,地图等)仍可以更改(即变异)。突变的例子有:

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

如果真的希望对象不可变,则必须使用const之类的东西。这是一种冻结对象的方法。冻结的对象不能再更改,也不能添加新属性。

示例:

Object.freeze()