web-dev-qa-db-ja.com

javascriptで定数の値を変更できるのはなぜですか

ES6はまだ標準化されていませんが、JSの 多くのブラウザーが現在サポートしているconstキーワードであることは知っています。

仕様では、次のように書かれています。

定数の値は再割り当てによって変更できず、定数は再宣言できません。このため、定数を初期化せずに宣言することは可能ですが、そうすることは無意味です。

そして、私がこのようなことをするとき:

_const xxx = 6;
xxx = 999;
xxx++;
const yyy = [];
yyy = 'string';
yyy = [15, 'a'];
_

xxxはまだ_6_で、yyyは_[]_です。

ただし、yyy.Push(6); yyy.Push(1);を実行すると、定数配列が変更されます。現時点では_[6, 1]_であり、ちなみに_yyy = 1;_で変更することはできません。

これはバグですか、何か不足していますか?最新のchromeとFF29で試しました

74
Salvador Dali

ドキュメントの状態:

...定数は再割り当てによって変更できません
...定数は再宣言できません

定数を再割り当てまたは再宣言していない配列またはオブジェクトに追加する場合、既に宣言および割り当て済みであり、定数が指す「リスト」に追加するだけです。

したがって、これはうまく機能します:

const x = {};

x.foo = 'bar';

console.log(x); // {foo : 'bar'}

x.foo = 'bar2';

console.log(x); // {foo : 'bar2'}  

この:

const y = [];

y.Push('foo');

console.log(y); // ['foo']

y.unshift("foo2");

console.log(y); // ['foo2', 'foo']

y.pop();

console.log(y); // ['foo2']

しかし、これらのどちらも:

const x = {};
x = {foo: 'bar'}; // error - re-assigning

const y = ['foo'];
const y = ['bar']; // error - re-declaring

const foo = 'bar'; 
foo = 'bar2';       // error - can not re-assign
var foo = 'bar3';   // error - already declared
function foo() {};  // error - already declared
126
adeneo

これは、定数が実際にreferenceを配列に格納しているために発生します。配列に何かを結合するとき、定数値を変更するのではなく、それが指す配列を変更します。オブジェクトを定数に割り当てて、そのプロパティを変更しようとした場合も同じことが起こります。

変更できないように配列またはオブジェクトをフリーズする場合は、 Object.freeze メソッド。すでにECMAScript 5の一部です。

const x = Object.freeze(['a'])
x.Push('b')
console.log(x) // ["a"]
30
Guilherme Sehn

これは、考えられるすべてのプログラミング言語で一貫した動作です。

Cを検討してください-配列は単なる修飾ポインタです。定数配列は、ポインターの値が変更されないことを意味しますが、実際にはそのアドレスに含まれるデータは自由です。

Javascriptでは、定数オブジェクトのメソッドを呼び出すことができます(もちろん、そうでなければ定数オブジェクトはあまり役に立たないでしょう!)これらのメソッドには、オブジェクトを変更する副作用があります。 JavaScriptの配列はオブジェクトであるため、この動作はそれらにも適用されます。

確実なのは、定数が常に同じオブジェクトを指すということだけです。オブジェクト自体のプロパティは自由に変更できます。

5
thorsday

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

さらに、重要な注意事項:

グローバル定数は、ウィンドウオブジェクトのプロパティにはなりません...

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const

2
Benjamin West

これにより、問題がより明確になると思います: https://codeburst.io/explaining-value-vs-reference-in-javascript-647a975e12a .

基本的には、常にメモリ内の同じアドレスを指すconstになります。そのアドレスに保存されている値は変更できますが、constが指しているアドレスも変更できません。

あなたが言及したconstの定義は、constがプリミティブ値を保持するアドレスを指している場合に真になります。これは、アドレスを変更せずにこのconstに値を割り当てることができないためです(これによりプリミティブ値の割り当てが機能するため)。constのアドレスの変更は許可されません。

constが非プリミティブ値を指しているかのように、アドレスの値を編集することができます。

1
Zyxmn

Objectをconstとして定義した後でも更新できた理由を検索しながら、この記事を読みました。そのため、ここでのポイントは、直接オブジェクトではなく、それに含まれる属性を更新できることです。

たとえば、私のオブジェクトは次のようになります。

const number = {
    id:5,
    name:'Bob'
};

上記の答えは、属性ではなくconstであるのはオブジェクトであると正しく指摘しました。したがって、次のようにしてIDまたは名前を更新できます。

number.name = 'John';

ただし、次のようにオブジェクト自体を更新することはできません。

number = {
    id:5,
    name:'John'
  };

TypeError: Assignment to constant variable.
0
Atul O Holic