web-dev-qa-db-ja.com

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

Axel Rauschmayer博士によるExploring ES6には const definition があります。

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

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

そして彼は書く

落とし穴:constは値を不変にしない

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

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

83
Mukund Kumar

[〜#〜] mdn [〜#〜] はうまくまとめています:

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

もっと簡潔に:constは不変のバインディングを作成します。

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

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

96
Mike Post

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を理解する方が簡単です。これは、値を変更せずに、変数に新しい値を割り当てるためです。

149
Candy Gumdrop

再バインド

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
14
user6445533

constは、最初に割り当てられた値を変更できないことを意味します。

まず、jsのを定義します。値には、ブール値、文字列、数値、オブジェクト、関数、および未定義の値を指定できます。

同様:人々はあなたの名前であなたを呼んでいます、それは変わりません。しかし、あなたは服を着替えます。人々とあなたの間のbindingはあなたの名前です。残りは変わる可能性があります。奇妙な例でごめんなさい。

それでは、いくつか例を挙げましょう。

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

ご覧のとおり、"first"に割り当てられた値をconstに変更しない限り、エラーは発生しません。最初に割り当てられた値を別の値に変更しようとすると、怒り、エラーが発生します。

したがって、これはconstを使用するときに知っている2番目のことです。つまり、宣言の値に初期化する必要があります。そうしないと、怒ってしまいます。

const Orphan;                    // error
const rich = 0;                  // no error
1
Inanc Gumus

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