キーワード「const」は値を不変にしません。どういう意味ですか?


85

ありますconstの定義ES6を探る博士アクセルRauschmayerでは:

constletのように機能しますが、宣言する変数はすぐに初期化する必要があり、後で変更できない値を使用します。[…]

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

それから彼は書いています

落とし穴:constは値を不変にしません

const 変数が常に同じ値を持つことを意味するだけですが、値自体が不変である、または不変になることを意味するわけではありません。

私はこの落とし穴と少し混乱しています。const誰かがこの落とし穴でを明確に定義できますか?


38
MDN説明は明確である:「CONST宣言値に読み取り専用の参照を作成し、それが保持する値が変数識別子を再割り当てすることができないだけということ、不変であるというわけではありません例えば、場合にコンテンツがある。オブジェクト、これは、オブジェクト自体を変更できることを意味します。」(強調鉱山)
Gerardo Furtado 2017年

4
これは、値が変更可能である場合(たとえば、オブジェクトの場合)、そのオブジェクトを変更できることを意味します(たとえば、プロパティの更新、追加、削除)。
Felix Kling 2017年

2
const x = "immutable"は不変であるため、Stringは不変です。const単に再割り当てを禁止します。

3
@ibrahimmahrir:パッシングA参照(JavaScriptがオブジェクトに対して何)パスと同じではないことによって(バインディングとの間の関係を記述し、値は無関係である)参照。
Felix Kling

2
@ibrahimmahrir:はい、それが問題です。参照渡し という用語には、非常に具体的な意味があります。
フェリックスクリング

回答:


97

MDNはそれをうまくまとめています:

const宣言は、値への読み取り専用参照を作成します。保持している値が不変であることを意味するのではなく、変数識別子を再割り当てできないことを意味します。たとえば、コンテンツがオブジェクトの場合、これはオブジェクト自体を変更できることを意味します。

より簡潔に言うと、constは不変のバインディングを作成します。

言い換えると、constは、varと同様に、何かを格納している可変のメモリチャンクを提供します。ただし、constは、同じメモリチャンクを参照し続ける必要があることを示しています。変数参照は定数であるため、変数を別のメモリチャンクに再割り当てすることはできません。

宣言した後、実際に一定で不変のものを作成するには、のようなものを使用する必要がありますObject.freeze()。ただし、これは浅く、キーと値のペアでのみ機能します。オブジェクト全体をフリーズするには、もう少し手間がかかります。パフォーマンスの高い方法でこれを繰り返し行うことは、さらに困難です。本当に必要な場合は、Immutable.jsのようなものをチェックすることをお勧めします


20
C用語で:法線var xが、の場合struct Object *x、aconst xstruct Object *const x。です。ポインタは変更できません。それが指しているものはできます。
モニカの訴訟に資金

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

再バインド

constそして、let宣言は、識別子と値との再バインド(再割り当て別名)が許可されるかどうかを制御します。

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に変更しない限り、エラーは発生しません。最初に割り当てられた値を別の値に変更しようとすると、怒り、エラーが発生します。

したがって、これはを使用するときに知っているかもしれない2番目のことですconst。これは、されたことは、その宣言の上の値に初期化されなければならないか、それが怒りになります。

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

0

ES6/ES2015 constキーワード:

constキーワードは(と宣言のようなブロックスコープ変数を宣言するために使用されますlet)。constletで変数を宣言することの違いは次のとおりです。

  1. 宣言された変数を再割り当てconstすることは できません。
  2. で宣言された変数は、宣言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;

上記の例では、次のことがわかります。

  1. myVariable宣言された変数は、let最初に宣言してから割り当てることができます。
  2. myConstant宣言された変数は、const宣言と割り当てを同時に行う必要があります。
  3. 変数myConstantを再割り当てしようとすると、次のエラーが発生します。

Uncaught TypeError:定数変数への割り当て

警告:に割り当てられた変数constは引き続き変更可能です:

で宣言された変数はconst再割り当てできませんが、それでも変更可能です。変更可能であるということは、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);

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.