JavaScriptは参照渡しpass-by-value言語か値渡しpass-by-reference言語か [Javascript]

このエントリーをはてなブックマークに追加

質問:

プリミティブ型(Number、Stringなど)は値によって渡されるけど、でもObjectは決まってない、なぜなら値渡し(オブジェクトを保持する変数が実際にはオブジェクトへの参照である場合)にも参照渡し(あるオブジェクトへの変数がそのオブジェクト自体を保持している時)の療法があるから。

あと、あんまり重要じゃないけど、引数を渡す慣習的なやり方の正しい方法ってある?あと、これに関するセマンティクスが何でべきか定義してるようなJavaScriptの仕様を抜粋したものとかって無いかな??

By Danail Nachev | 質問日時: 2009年2月5日 21:23



回答1:

これはJavascriptで面白い問題だよね。こんな例を考えてみよう:

function changeStuff(a, b, c)
{
a = a * 10;
b.item = "changed";
c = {item: "changed"};
}
var num = 10;
var obj1 = {item: "unchanged"};
var obj2 = {item: "unchanged"};
changeStuff(num, obj1, obj2);
console.log(num);
console.log(obj1.item);
console.log(obj2.item);

これは次のような出力をする:

10
changed
unchanged

もし純粋な値渡しでだった場合、 obj1.itemを変更することは関数の外ではobj1への影響は全く無い。
もし参照渡しだった場合、話が変わってくる。 num100obj2.itemchangedになる。

そうじゃなくて、考える状況は渡されたアイテムが値渡しであって、でも値渡しされるアイテムそれ自身は参照になってる状況だ。

技術的には、これはcall-by-sharingって呼ばれてる。

実際には、(numobj2のように)パラメータ自体を変更した場合、それはパラメータに渡されるアイテム自身には影響を与えない。でも、(obj1のように)パラメータの内部を変更すると、その影響は(obj1に)伝わっていく。



回答2:

基本常に値渡しだけど、オブジェクトの場合は変数の値は参照になってる。だから、オブジェクトを渡してそのメンバーを変更すると、その変更は関数の外でも引き継がれる。
これは、参照渡しのように見える。でも、実際にオブジェクト変数の値を変更すると変化が引き継がれないことがわかるので、それが本当に値渡しであることの証明になってる。

例:

function changeObject(x) {
x = {member:"bar"};
alert("in changeObject: " + x.member);
}
function changeMember(x) {
x.member = "bar";
alert("in changeMember: " + x.member);
}
var x = {member:"foo"};
alert("before changeObject: " + x.member);
changeObject(x);
alert("after changeObject: " + x.member); /*変更は引き継がない */
alert("before changeMember: " + x.member);
changeMember(x);
alert("after changeMember: " + x.member); /* 変更は引き継ぐ */

出力:

before changeObject: foo
in changeObject: bar
after changeObject: foo
before changeMember: foo
in changeMember: bar
after changeMember: bar

By Tim Goodman | 回答日時: 2011年3月15日 16:38



Source: Is JavaScript a pass-by-reference or pass-by-value language?

共有 コメント