const の配列の値が変えられるのはなぜでしょうか?
JavaScript
1const list = []; 2list.push(3); 3list.push(44); 4list[0] += 1; 5console.log(list);
こうすると結果は[ 4, 44 ]となります。
Constと定義しているのになぜ配列の中身が変更されるのでしょうか?
また、そもそもなぜPushできるのでしょうか?
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
![guest](/img/icon/icnUserSample.jpg)
回答8件
0
const 宣言は、値への読み取り専用の参照を作ります。その値が不変ということではなく、その変数識別子が再代入できないというだけです。たとえば、定数がオブジェクトのコンテンツの場合、オブジェクトのコンテンツ(例 その引数)自体は変更可能です。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/const
Object.freeze()
Object.freeze()を使えば、配列やオブジェクトを不変に出来ますが、以下のデモコードの通り、ネストされている場合は可変のままになります。
配列
// #1 const list1 = [] list1.push(1); console.log(list1); //[ 1 ] // #2 const list2 = []; Object.freeze(list2); //list2.push(2); //TypeError: Can't add property 0, object is not extensible // #3 const list3 = [[]]; Object.freeze(list3); list3[0].push(3); console.log(list3); // [ [ 3 ] ]
## オブジェクト
// #1 const obj1 = { id: 1 } obj1.id = 2; console.log(obj1.id); //2 // #2 const obj2 = { id: 10 } Object.freeze(obj2); obj2.id = 20; console.log(obj2.id); //10 // #3 const obj3 = { id: 100, items: { id: 1000 } } Object.freeze(obj3); obj3.items.id = 2000; console.log(obj3.items.id); //2000
投稿2018/04/10 04:12
編集2018/04/10 04:24総合スコア2415
0
それは配列の中身を変えているからですよ. もちろん, 配列そのものを交換する(変数list
への代入)はエラーとなります.
const list = []; list = [];//エラー
投稿2018/04/10 04:11
総合スコア4756
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
JavaScript > リファレンス > 文と宣言 > const
const 宣言は、値への読み取り専用の参照を作ります。その値が不変ということではなく、その変数識別子が再代入できないというだけです。たとえば、定数がオブジェクトのコンテンツの場合、オブジェクトのコンテンツ(例 その引数)自体は変更可能です。
ES6のconstを使い倒すレシピ1 - 前提共有編 〜 JSおくのほそ道 #034
constの盲点
ではconst化すれば、あらゆる値の状態変化がないことを保証できるかというと、そうではありません。
const宣言の挙動としては**「再代入を許容しない」**ことにあります。再代入以外は許容します。
とのことです。
投稿2018/04/10 04:12
総合スコア38337
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
ベストアンサー
const は再代入不可
既出の回答通り、const
は再代入不可にするだけであり、改変は可能です。
詳細は出尽くしている為、割愛します。
Object.freeze()
こちらが本題。
HayatoKamono さんの回答に対し、defghi1977 さんが次のコメントを残しています。
エラーにしたい場合はどうすりゃいいんでしょうね? Proxyでラップしてsetされたらthrow Errorとかかな
プロパティの変更はエラーになりませんが、追加はエラーになるので再帰的にオブジェクトを freeze する事で影響範囲を広げる事は出来ます。
しかし、Object.freeze
はプロパティ変更に対しては不変であってもエラーを発生させません。
ここで、[[Prototype]]
上のプロパティと直属のプロパティが別管轄である事に注目します。
JavaScript
1var object = Object.create({a:{b:{c:{d:{e:true}}}}}); 2 3deepFreezeFromObject(Object.getPrototypeOf(object)); // [[Prototype]] を freeze 4deepFreezeFromObject(object); // 直属を freeze 5object.a = 1; // TypeError: Cannot assign to read only property 'a' of object '#<Object>'
object.a
は存在しないのでプロパティ追加扱いになるというロジックです。
が、[[Prototype]]
を辿ってプロパティ改変を試みれば、TypeErrorにならずに不変である事象に変わりはないので、ネタにしかならないですね…。
JavaScript
1Object.getPrototypeOf(object).a = 2; // エラーにならない 2console.log(object.a); // {b:{c:{d:{e:true}}}}
Re: Nippun さん
投稿2018/04/10 13:09
総合スコア18182
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
![guest](/img/icon/icnUserSample.jpg)
0
const
はあくまで、再代入が不可能になるだけです。オブジェクトの中の各要素までは保護されていません。
このページの例にあるように、配列にpushすることも普通にできます。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/const
投稿2018/04/10 04:12
総合スコア1524
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
Array オブジェクトはミュータブル(変更可能)だからです。
js
1var a = 1; 2var b = a; 3a = 2; 4a === b; // false 5 6var a = [1]; 7var b = a; 8a[0] = 2; 9a === b; // true
投稿2018/04/10 04:16
総合スコア36601
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
JavaScriptはオブジェクトについて参照渡しだなんて、信じない
今回の質問はこれが分かりやすいと感じました。
JavaScriptはオブジェクトや、それから派生して作られた配列等は
メモリ空間上に配列がポコンと作られ、list
変数にメモリ空間上のアドレス値が格納されます。
JavaScript
1console.log([] === []) // false
この結果がfalseになるのは、2つの配列をメモリ空間上に生成してアドレス値同士で比較したからです。
だから違うものとしてfalseが帰ってきます。
constが見張り続けるのはこのメモリ空間上のアドレス値
です。
その中にあるメモリ空間内の実体に関しては知らないというスタンスです。
でもまぁ、list.push(hoge)
みたいなので変更しまくる場合、心情的にはlet
を使いたくなりますね。
eslint等ではlist.push
を使いまくったからといって再代入はしていない為、不要なlet
を許してくれず、const
で宣言しろと怒られます。
投稿2018/04/10 04:35
総合スコア21177
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
javascriptのconstは、再代入が出来ない(一旦値が入れられたら、後で変えることができない)という意味です。
数字や文字列のようなリテラルだけでなく、質問のコードのように配列を代入することも可能です。
質問のコードで、listの値は、1つの配列(配列への参照)から変わってはいません。
そして、listから参照されているのは配列なので、値を変更したりpushやpopなど、配列で出来る事は何でもできます(配列なのですから)
投稿2018/04/10 04:31
総合スコア6915
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/04/10 04:26
2018/04/10 04:27