JavaScriptは値渡しなのでしょうか?共有渡し(参照の値渡し)なのでしょうか?普通のObjectはすべて共有渡しだと思うのですが、プリミティブ型(?)については違うようなのです。しかし、StackOverflow(※)でもまとまっていないようで、よくわかりませんでした。詳細を分かる方がいれば、下記について教えて下さい。
※参考: StackOverflow: Is JavaScript a pass-by-reference or pass-by-value language?
-
値渡しになる型はあるのでしょうか?ある場合は、どの型がなるのでしょうか?
-
1.の型のうちmutableな型はあるのでしょうか?ある場合は、mutableな型の破壊的メソッドはどのようなものがあるのでしょうか?
-
値渡しであることが分かる(共有渡しでは説明できない)コードはありますでしょうか?
-
C++やC#で言う所の参照渡しも存在するのでしょうか?その場合はどのような物が参照渡しになるのでしょうか?
-
ECMAScript2015仕様書やMDN JavaScriptなどの公式または公式に準ずる資料で上のことに言及している部分はどこになるのでしょうか?
私の考えでは、インクリメント/デクリメント(++
/--
)を特殊なx+=1
/x-=1
であると解釈すれば、すべて共有渡しと解釈して問題ないのではないか?と思っています。反例があれば教えて欲しいです。
【注記】
ここでの値渡しはcall-by-value、参照渡しはcall-by-referenc、共有渡し(参照の値渡し)はcall-by-sharingを意味します。違いについては「値渡しと参照渡しの違いを理解する」の記事を参考にして下さい。回答の際は厳密に用語を分けていただきますようお願いします。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答5件
0
ベストアンサー
実装面で見るならば、Reference 型を「参照の値渡し」、Primitive 型 (ToPrimitive で値に変化がない型)を「値渡し」と呼称して良いと思います。
JavaScript
1function foo (a) { 2 a[0] = 1; 3 a = {}; 4} 5 6var array = [], string = '0'; 7foo(array); 8foo(string); 9console.log(array); // [1] (参照の値渡し) 10console.log(string); // "0" (値渡し)
ただし、ECMAScript 仕様では「値渡し」「参照の値渡し」には言及されてなく、実装面の意味合いが強いと考えています。
詳細 ECMA-262-3 第8章 評価戦略 - mixi Engineers' Blogが比較的詳しいですが、説明をぼかして書いている部分も見受けられます。
MDN ではプリミティブなパラメータ (数値など) は値渡しで関数に渡されますとありますが、厳密な定義でいうなら MDN は間違っている解説も多いので参考程度に留めるのが良いと思います(解説が古かったり、英語解説だけに載っていたり、用語が間違っていたりする記述を何度も見ています)。
投稿2015/08/14 23:52
編集2015/08/14 23:54総合スコア18189
0
一言で言うなら、全て共有渡しです。
(ここでの共有渡しとは、値の実体を複製するのではなく、その存在を変数同士で共有するように渡すこと、
ただし参照の値渡しのような具体的な実装に踏み込んだものとも違って、
何かを渡すというよりむしろ、1つの値に別の名前を付けさせるという方向性(最も仕様の流れに近い)の概念とします。)
仕様ではプリミティブ型とオブジェクト型で渡され方が変わるようには書いていませんし、
オブジェクト値の実体が参照だとも書かれていません。
ならば全てが共有渡しと見るべきです。
そもそも渡され方は渡し方で決まるべきで、渡される値によって異なると言うのは不自然です。
JSでは渡し方はひと通りですから、渡され方もひと通りなのです。
因みに仕様のReference型は変数の解決における内部処理に使われるものであって、
紛らわしいですが渡され方の問題とは軸がズレていて本質的には関係ないものです。
投稿2015/08/15 10:29
編集2015/08/15 10:41総合スコア100
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2015/08/15 11:47
2015/08/15 13:24
2015/08/18 09:44
2015/08/18 10:37
0
(私が初歩的な勘違いをしている気がするのですが)もし全てが共有渡しの場合、以下の例では全て2が出力されると思うのですが、これはbが値渡しである実証例にはならないでしょうか?
javascript
1function foo (b,d) { 2 a = 2; 3 c[0] = 2; 4 console.log(b); //1 5 console.log(d[0]); //2 6} 7 8a =1,c=[1,0]; 9foo(a,c); 10console.log(a); //2 11console.log(c[0]); //2
投稿2015/08/15 12:04
総合スコア2068
0
何度もすみません。
一応読み直して基本的な疑問の答えにはなるかと思うので、検索に掛かったページを挙げておきます。
11.2. By Value Versus by Reference - JavaScript: The Definitive Guide, 4th Edition.
参考になれば幸いです。
投稿2015/08/14 21:38
編集2015/08/14 21:49退会済みユーザー
総合スコア0
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2015/08/14 23:58
2015/08/15 00:08
退会済みユーザー
2015/08/15 00:26
2015/08/15 00:37
2015/08/15 01:05
0
まず最初に、言語の仕様に、『値渡しや参照渡し、あるいは共有渡しを使うのか』を明記する必要もなければ理由もありません(言語によるでしょうが少なくともJavaScriptでは必要ないと思われる)。
なぜかというと、『値渡しや参照渡し、あるいは共有渡しを使うのか』という話は、実装の問題だからです。
仕様では、変数の渡し方に関わらず、どういうコードを書いたらどういう結果になるのかだけ決めればよいだけなのです。
どのように変数の値を渡したらメモリ効率がよいのか、あるいは速度が速いのかなどは何を優先するかによっても変わってくるので、実装する側の人間が決めれば良い話なので仕様側で決める必要はありません(別に決めてしまっても良い)。
そこで改めて質問の趣旨を考えてみると、
1.ECMAScriptの仕様で『値渡しや参照渡し、あるいは共有渡しを使うのか』が決められているのか?
2.V8などの実際の実装で『値渡しや参照渡し、あるいは共有渡しを使うのか』がどうなっているのか?
という2種類の疑問がごっちゃになっているように思われます。
1のほうであれば、仕様を全部読めば、決められているのかいないのかははっきりすると思います。
(たぶん決められていなさそう…)
また、2のほうであれば、実際の実装のソースを読むしかないと思います。ただし、仮にV8の実装では共有渡しだったとしても、他の実装では違う可能性もあるので、すべての実装でどうなっているのか知りたいのならば、片っぱしからソースを読む必要が出てくるので現実的ではないと思われます。
投稿2015/08/18 06:30
総合スコア314
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2015/08/18 06:49
2015/08/19 02:34 編集
2015/08/20 10:18
2015/08/20 21:46 編集
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2015/08/15 00:32
2015/08/15 01:02