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

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

新規登録して質問してみよう
ただいま回答率
85.48%
オブジェクト

オブジェクト指向において、データとメソッドの集合をオブジェクト(Object)と呼びます。

JavaScript

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

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

Q&A

解決済

4回答

3211閲覧

配列、オブジェクトなどのconsole.log出力値がおかしい。(短いコードです)

退会済みユーザー

退会済みユーザー

総合スコア0

オブジェクト

オブジェクト指向において、データとメソッドの集合をオブジェクト(Object)と呼びます。

JavaScript

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

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

1グッド

0クリップ

投稿2018/02/07 01:31

私の予想では下記のコードではconsole.logの値は0になるとおもったのですが。実際は1でした。これはなぜですか?

javascript

1 var a=[{"y":0}] 2 var=a; 3 b[0].y=1; 4 console.log(a[0].y);//0ではなく1と出力される

この現象は下記のコードでもおきます

javascript

1 var a={"y":0} 2 var=a; 3 b.y=1; 4 console.log(a.y);//0ではなく1と出力される

javascript

1 var a=[0] 2 var=a; 3 b[0]=1; 4 console.log(a[0]);//0ではなく1と出力される
miyabi-sun👍を押しています

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

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

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

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

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

yambejp

2018/02/07 01:43

とりあえず全角の「b」はわざとでないなら半角に書き換えて下さい
guest

回答4

0

ベストアンサー

JavaScriptでは、配列を含めたオブジェクトの代入は、コピーではなく、同じオブジェクトを共有する形となります。

オブジェクトをコピーしたい場合には、配列であれば[...arr].concat()を使う、ObjectであればObject.assign(IE11は未対応)を使う、どちらの場合でもいったんJSON化してから戻す、などの方法があります。

投稿2018/02/07 01:37

maisumakun

総合スコア145184

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

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

0

まずはこのコードを見てください。

JavaScript

1var a = [100]; 2var b = a; 3console.log(a === b); // true <- わかる 4console.log(a === [100]); // false <- !?!?!?

JavaScriptの世界ではArrayやObject等は生成時に唯一の目に見えないID(以下ユニークID)が与えられます。
ユニークIDの実体はオブジェクトが格納されているメモリ空間上のアドレスです。
var a = [100]には配列の実体そのものではなく、メモリ空間上のアドレス、つまりユニークIDという特殊な数値が代入されています。

[100] === [100][100]という配列を2個生成して、それぞれにユニークIDを割り振ります。
オブジェクト同士の比較演算では、このユニークID同士のみを比較します。
ユニークID以外は完全に一致する2つの[100]ですが、ユニークIDが異なる為にfalseになるのです。

※ユニークIDと連呼していますが、これは説明し易いから呼んでいるだけで正式な名称ではありません。この回答文以外ではメモリ空間のアドレス等の名称で呼んで下さい。


この現象は配列やオブジェクト操作の時にも影響されます。

JavaScript

1var a = [1]; 2var b = [1]; 3a[0] = 2; 4console.log(a, b); // [2], [1] <- わかる 5 6var c = b; 7c[0] = 3; 8console.log(a, b, c); // [2], [3], [3] <- !?!?!?

配列やオブジェクトの値を操作する場合、ユニークIDに従ってメモリ空間上にある値を直接更新します。
その結果、上記のコードではc[0]の変更の影響がb[0]に出ています。

ちなみにaとbは別々に配列を作っていますので相互不干渉です。


この仕様、一部のケースではとても困ります。

  • 失敗したら変更操作を取り消したい
  • 変更前後で比較検証したい

配列やオブジェクトのプロパティを操作したら本物に影響が出てしまうわけですからね。
そこで、全くのクローンを生成する手法が用意されていたり、編み出されています。

分かりやすい簡単なコードはこれです。

JavaScript

1var a = [1, 2, 3, 4, 5]; 2var b = []; 3for (var i = 0; i < a.length; i++) { 4 b.push(a[i]); 5} 6 7b[0] = 10; 8console.log(a, b); // [1, 2, 3, 4, 5], [10, 2, 3, 4, 5]

aとbは別々の配列を作る宣言をしていますので、ユニークIDは別個です。
その後a配列の要素を一つずつbにコピーしていますが、
aとbは既に切り離されていますし、a配列の要素は全て数値なのでユニークIDのコピーは発生しません。

bはaのクローンを作る事に成功したのです。
従って、a配列には影響を与えずにb[0] = 10と意図通りの操作を行う事に成功しています。

この手法は「シャローコピー」、「ディープコピー」、「クローン」などといった用語で説明されています。
もし必要になった際には、これらのワードで検索を掛けてみてください。

投稿2018/02/07 02:19

編集2018/02/07 02:35
miyabi-sun

総合スコア21158

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

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

0

余談ですが、

var b=a; // bは全角文字 b.y=1; // bは半角文字。上のbとは別の変数

投稿2018/02/07 02:04

編集2018/02/07 02:06
tkturbo

総合スコア5572

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

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

maisumakun

2018/02/07 02:42

JavaScriptの場合、識別子として使える文字はUnicodeの文字プロパティで定義してあるので、何がOKなのかわかりづらいですね… RubyやPHP(UTF-8のソースコード)の場合、ASCII外の文字はすべて識別子の一部にできます。
guest

0

javascript

1// この1行を追加して考えてください。やっていることは変わりません。 2var c = {"y":0}; 3var a = [c]; 4var b = a; 5b[0].y=1; 6// b[0] は c なので、これは、c.y = 1 と同じです。これで、c.y が 1 になりました。 7console.log(a[0].y); 8// a[0] は c なので、c.y つまり 1 が出力されます。

投稿2018/02/07 01:40

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問