关键字“ const”并不使该值不可变。它是什么意思?

这是 探索 ES6中的 常数定义作者: Axel Rauschmayer 博士:

const的工作原理与 let 类似,但是声明的变量必须是 立即初始化,< strong > 带有一个不能更改的值 后来

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

然后他开始写作

陷阱: const 不会使值不可变

const只意味着一个变量始终具有相同的值, 但是这并不意味着值本身是不可变的。

我对这个陷阱有点困惑。有人能清楚地定义 const这个陷阱吗?

9447 次浏览

MDN sums it up nicely:

The const declaration creates a read-only reference to a value. It does not mean the value it holds is immutable, just that the variable identifier cannot be reassigned. For instance, in case the content is an object, this means the object itself can still be altered.

More succinctly: const creates an immutable binding.

In other words: const, like var, gives you a mutable chunk of memory in which you're storing something. However, const dictates that you must keep referring to that same chunk of memory – you can't reassign the variable to a different chunk of memory, because the variable reference is constant.

To really make something constant and unchanging after you've declared it, you need to use something like Object.freeze(). However, that's shallow and only works on key/value pairs. Freezing an entire object takes a bit more effort. To do so repeatedly in a performant way is yet more challenging. If you really have a need for that, I'd recommend checking out something like Immutable.js

When you make something const in JavaScript, you can't reassign the variable itself to reference something else. However, the variable can still reference a mutable object.

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;

In the case of primitives such as strings and numbers, const is simpler to understand, since you don't mutate the values but instead assign a new value to the variable.

Rebinding

const and let declarations control whether rebindings (aka reassignments) between identifiers and values are allowed:

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);

Immutability

Immutability is controlled at the type level. Object is a mutable type, whereas String is an immutable type:

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

const means: you can't change the initially assigned value.

First, define, what is a value in js. Value can be: Booleans, strings, numbers, objects, functions, and undefined values.

Like: People are calling you with your name, it's not changing. However, you change your clothes. The binding between the people and you is your name. The rest can change. Sorry for the weird example.

So, let me give you some examples:

// 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

As you can see, unless you're not changing the "first" assigned value to a const, no error. Whenever you try to change the first assigned value to something else, it gets angry, and it gives an error.

So, this is the second thing you might know when using const. Which is, it should be initialized to a value on its declaration or it will be angry.

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

ES6/ES2015 const keyword:

The const keyword is used to declare a block scoped variable (like declaring with let). The difference between declaring a variable with const and let is the following:

  1. A variable declared const cannot be reassigned.
  2. A variable declared with const has to be assigned when declared. This is a logical consequence of the previous point because a variable declared with const cannot be reassigned, that's why we have to assign it exactly once when we declare the variable.

Example:

// 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;

In the above example we can observe the following:

  1. The variable myVariable declared with let can first be declared and then be assigned.
  2. The variable myConstant declared with const has to be declared and assigned at the same time.
  3. When we try to reassign the variable myConstant we get the following error:

Uncaught TypeError: Assignment to constant variable

Caveat: The variable assigned with const is still mutable:

A variable declared with const just can't be reassigned, it is still mutable. Being mutable means that the data structure (object, array, map, etc) which was assigned to the const variable still can be altered (i.e. mutated). Examples of mutation are:

  1. Adding/deleting/altering a property of an object
  2. Changing the value of an array at a specific array index

If really want an object to be not mutable you will have to use something like Object.freeze(). This is a method which freezes an object. A frozen object can no longer be changed and no new properties can be added.

Example:

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);