質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.46%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

4回答

1295閲覧

JavaScript 変数への代入の違い

blueletter5

総合スコア24

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2020/08/21 07:38

<単純なデータ型>

  1. 以下のようなケースでxに5という値を代入すると1行目の「let x = 1;」で「x」の値が5に変わるというのは理解できます。

この場合、2行目は「y」の値は「1」のままです。「5」でないのがわかりません。
代入したことによって「let y =x」へは影響を及ぼさないのはなぜですか?
少なくともスコープの範囲以内は代入の影響が出るものと考えてしまいます。

{

let x = 1;
let y = x;

x = 5;

console.log(x); //5
console.log(y); //1

}

<配列>
2.このような配列の場合、「x[0]」に配列である[1, 2];が代入されているわけですよね。
以下のように「x[0]」に5を代入した場合、console.logで見てみると、[5, 2]となるのは理解できます。

しかし、2行目の「let y = x;」も[5, 2]となっています。
上の単純なデータ型のケースをもとに考えるならば、ここは[1, 2]のままでないのはなぜなのでしょうか? 試しに自分で「x[1]」に書き換えてみると両方とも「1, 5」となります。

{

let x = [1, 2];
let y = x;

x[0] = 5;

console.log(x); //[5, 2]
console.log(y); //[5, 2]

}

なぜ、単純なデータ型と配列ではパターンが異なってくるのでしょうか?

初心者です。学習中でまだ基礎的な段階なのですが、つまづいてしまいました。

分かる方いらっしゃいましたら教えて下さい。よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

1行目の「let x = 1;」で「x」の値が5に変わるというのは理解できます。

違います。JavaScriptの場合、代入はあくまでその時点で行われる操作です。let y = x;は、「yx現在の値を代入する」という意味で、その後にxが変化しようがyには無関係です。

上の単純なデータ型のケースをもとに考えるならば、ここは[1, 2]のままでないのはなぜなのでしょうか?

はい、単純な数値とオブジェクトでは考え方が異なります。

投稿2020/08/21 07:54

maisumakun

総合スコア145208

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

blueletter5

2020/08/23 03:41

値渡し、参照渡しなど単純なデータ型と配列、オブジェクトでは異なるのですね。どうもありがとうございました。
guest

0

ベストアンサー

2.このような配列の場合、「x[0]」に配列である[1, 2];が代入されているわけですよね。

違います。**「x」**に配列である[1, 2];が代入されています。「x」と「x[0]」は全く異なるものです。それを元にもう一度考え直してみてください。


ここから先は詳しい説明なのですが、私の力不足で小難しい表現になってしまっています。初心者のかたは混乱するだけなので読まないことをお勧めします

JavaScript(ECMAScript)の変数というのはオブジェクトに対するラベルのようなものです。代入というのは、右辺の評価値に対して左辺の名前を付けているだけ、左辺値を右辺値に束縛しているだけです。これはプリミティブ値でもオブジェクトでも同じです。


初めに1.のコードを見に行きましょう。

let x = 1;

これはリテラル1の評価値であるnumberの1に対して、「x」という名札を用意し、紐付けましたという意味です。これを「x」をnumberの1に束縛する(bind)、numberの1を「x」に代入する(assigne)と言います。

let y = x;

次のこの文は何でしょうか?まずすることは右辺の評価値を求める事です。xを評価するというのは「x」の名札がつけられているを見に行くと言うことです。これは先程の文でnumberの1に紐付けたのでした。ですので、xの評価値はnumberの1であり、前の文の1の評価値と全く同じ物です。お気づきの通り、後は同じです。「y」という名札が用意され、numberの1に紐付けられたのでした。

x = 5;

letがありませんが、名札はもう作ってあるので再度用意しないと言うことに過ぎません。さて、これはいわゆる再代入となりますが、これは、名札を別の物に紐付けると言うことです。5の評価値はnumberの5ですので、「x」はnumberの5に紐付けられるようになりました。このとき、「y」は何もしていません。相変わらずnumberの1を見に行っていますので、何も影響は受けません。

そして、xyについてそれぞれ確認すると5と1になるというのがよくわかると思います。


では、配列のパターンを見ていきましょう。

let x = [1, 2];

先程違い配列なのですが、まず、リテラル[1, 2]とはどのような物なのかを理解する必要があります。これは「0番目(プロパティ"0")が1の評価値、1番目(プロパティ"2")が2の評価値となる新たに作成された配列(Array)」が評価値です。個々で注意して欲しいのは、配列が生成されていると言うことです。そして、この新たな配列に紐付けられた名札「x」が用意されたと言うことになります。

let y = x;

さてさて、次の文のxの評価値は何でしょうか?そう、先程の文で作成された配列です。ここでまた配列が作成されるのではなく、「x」が示す物がそのまま「y」が示す物になります。言い換えれば、「x」と「y」は同じ物に束縛されています。

気づきましたか?ここまでは先程と同じです。

x[0] = 5;

この文は最初の1.と異なります。もしx = 5;であれば、1.と全く同じ説明で良かったはずです。「x」が示す物がexotic objectである配列であるためちょっと特殊な処理があるのですが、ここではその性質はほとんど無視して説明が可能です。この文はx["0"] = 5;とも解釈できます。"0"はプロパティ名で、配列の場合は0番目も意味します。このような書き方では、変数の代入ではなく、プロパティへの代入とみなされます。

JavaScriptのオブジェクト(配列もオブジェクトの一種)はプロパティという物を持ちます。プロパティは名前(文字列またはシンボル)と値の組合せです。プロパティは変数と似ており、これもまた名札のような物です。xの評価値、つまり、「x」の名札が示す先の配列もまた、プロパティ"0"にnumberの1、プロパティ"1"にnumberの2というがあります(他にも特殊なプロパティ"length"等も設定されています)。今回の文は、このプロパティ"0"に5の評価値であるnumberの5を代入するということです。

もっと別の言い方で言いましょう。もともとは、「x」の名札が示す先の配列があり、その配列が「0」の名札を持っていて、その「0」の名札が示す先がnumberの1でした。しかし、今回の代入文によって、「0」の名札が示す先がnumberの5に変更された言うことです。

さて、このとき「x」の名札が示す先と「y」の名札が示す先は変わったでしょうか?いいえ、変わってはいないはずです。変わったのは配列が持っていた名札であって、「x」も「y」も何も変えていません。これら二つは最初の文で作成された配列を変わらずに示し続けています。

ここまで来たら後はわかりますね。xを評価するとき、先程の配列になるという話でしたが、console.logでは配列の中にある名札についても評価して表示します。それらは、5と2でしょう。では、yを評価するときはどうなるかというと、これはxを評価したときと同じ配列なのですから、同じように5と2となるというわけです。


以上ですが、この話はJavaScriptについてです。PythonやRubyも同じような言語設計になっていますが、C等は変数は名札ではなく箱なので全く異なります。まだ、よくわからないという内は、あまり気にしない方が良いかと思います。

投稿2020/08/21 12:49

raccy

総合スコア21735

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

blueletter5

2020/08/23 03:37

ご丁寧にありがとうございました。
guest

0

変数とプロパティ

「変数」と「プロパティ」を区別して下さい。

変数の再代入

必ず、値ごと変わります。
Object型もPrimitive型も挙動は同じです。

プロパティの書き換え

プロパティに紐付くオブジェクトを格納している全ての変数に影響します。

Re: blueletter5 さん

投稿2020/08/21 10:27

編集2020/08/21 10:38
think49

総合スコア18170

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

blueletter5

2020/08/23 03:42

回答ありがとうございました。 データ量の大きなObject型と単純なデータ型では異なってくるのですね。
guest

0

JavaScriptに限った話じゃないんだけど、今のマシンは64bit(8バイト)に収まるデータは素早く処理できる。だから数値はデータを値そのものとして扱う。JavaScriptの他の型、例えば文字列や配列はデータ長が決まっておらず、長くなることが多いのでデータはヒープという領域に格納し、変数にはそのデータの場所(アドレス)を入れておく。ヒープに格納される型はたいてい参照型と呼ばれ、変数とデータは切り離して考えないといけない。
x = [1, 2]; // [1, 2]はヒープに格納され、xにはそのデータへの参照が格納される
y = x; // yにはxに格納されている参照が格納される。つまりyにはヒープの中にある[1, 2]への参照が格納される
このときxとyは同じものを参照しているのでxの中身を書き換えるとyの中身も変わります。

ちなみに配列と文字列では中身を書き換えたときの挙動が変わります。これは言語によって仕組みが全然違ったりするのですが、JavaScriptの場合、配列は書換え可能であり、文字列は書換え不可能だからです。文字列の操作は書換えてるのではなくて新しく生成しています。ここは難しいところですね。少しずつ慣れていきましょう。

投稿2020/08/21 11:35

編集2020/08/21 11:37
anndonut

総合スコア667

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

blueletter5

2020/08/23 03:39

値渡し、参照渡しなどのキーワードで合致しました。 配列やオブジェクトはデータが大きくなるのでそのようになるわけですね。 おっしゃる通り慣れて行かねばなりません。 回答ありとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.46%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問