2728


JavaScriptの参照に関する記事でよく、オブジェクトは共有渡しで、プリミティブ値は値渡しと書かれていますが、仕様書をみても当該の記述を見つけられません。  
仕様書を読む限り区別がない、つまり全てが値渡しの様に見えてしまいます。

もしくはReference型にbaseとして格納されているのは値を構成するデータ配列ではなく、値の存在そのもの、つまり参照（ポインタ）に近い概念であって、結局実は全部が共有渡しということなのでしょうか？

例えばProperty Accessorsの仕様で 「Return a value of type Reference whose base value
is bv」
というのは、作成されるReferenceのbaseにbvそのものを格納する→bvをデータとして複製して格納ではなく、その存在そのものを格納→実際は参照（ポインタ）に当たるものが格納されるイメージ、というニュアンスなのでしょうか？


CC BY-SA 3.0
2014-12-25T05:48:19.313
2544
2016-02-15T03:10:40.690
2016-02-15T03:10:40.690
8000
5721
question
javascript
Javascriptの仕様で「オブジェクトは共有渡しで、プリミティブ値は値渡し」と区別しているのか


引数の動作については、JavaScript が実装している ECMAScript の仕様書がある程度参考になるかと思います。
以下の様な箇所で触れられています。

  * <http://alpha.mixi.co.jp/entry/2012/10796/#ecma-263-3-8-introduction>
  * <http://dmitrysoshnikov.com/ecmascript/chapter-8-evaluation-strategy/>
  * <http://www.ecma-international.org/ecma-262/5.1/#sec-10.4.3>
  * <http://www.ecma-international.org/ecma-262/5.1/#sec-13.2.1>

ECMA263-3 の第八章内にある「ECMAScript での実装」にも書かれている通り、全ては共有渡し（Call by sharing）です。

質問で @JSer さんがおっしゃっているとおりの理解で間違いないかと思います。


CC BY-SA 3.0
2014-12-25T06:35:03.413
2550
2014-12-25T06:35:03.413
2944
2544
answer


まず、参照渡し、値渡しと分けて考えなくても良いのではないでしょうか。 考えると混乱するだけです。

ほとんどのプログラミング言語での関数呼び出しに対する、私の理解は、

「 **全て値渡しをする。** 」

であり、Javascript 言語について特別なことは、

「 **変数自体のアドレス値を扱う指定がない** 」

という特徴があるだけです。この理解の仕方で納得できるでしょうか？

Javascript
では、オブジェクトを引数として関数が呼び出される時に、実際はオブジェクトを指し示すアドレス値が渡されることになります。変数（入れ物）のアドレス値を渡すような指定はできません。プリミティブ型（文字以外）の場合でも、変数の中身が渡されます。これも変数自体のアドレス値を渡すことになる指定はできません。「変数にオブジェクトが入っている」とは実質オブジェクトを指すアドレス値が入っているとみなせ、関数にオブジェクトを渡すとは、オブジェクトを指すアドレス値を渡すことと言えます。くどいようですが変数を渡すことではありません。

混乱の原因は言語によって、「XXX
渡し」の言葉の意味するところが変わることです。参照渡し、共有渡しなどの言葉は、それぞれのプログラミング言語での記述の概念を理解しやすくするための言い回しと考える程度でよく、世の中には、値しかない、と割り切ったほうが理解がしやすいかと考えます。
（共有が参照渡しと違うのは、アドレス値が複製される、ということだけでしょうか、そこがもやもやします。）

※文字(string)型はオブジェクトと同じように扱われます。  
※ここではポインタに相当するものをアドレス値と呼んでいます。（メモリ上のアドレスの値そのままということではない）  
※ ここで扱うプリミティブ型とは、`boolean`, `string` と `number` であり、`null` と `undefined` を除く。

> 例えばProperty Accessorsの仕様で 「Return a value of type Reference whose base value
> is bv」
> というのは、作成されるReferenceのbaseにbvそのものを格納する→bvをデータとして複製して格納ではなく、その存在そのものを格納→実際は参照（ポインタ）に当たるものが格納されるイメージ、というニュアンスなのでしょうか？

原文からは、「複製」や「作成」や「格納」という言葉を読み取れませんでした。私には Javascript
を使ってメタに書けば以下のような感じで理解できただけです。

[code]

    return Reference({
        base_value       : by,        // MemberExpression からの値
        referenced_name  : nameValue, // IdentifierReference からの値
        strict_reference : true,      // true か false
    })
    
[/code]

### 追記:

調べたら、関連するものがありました。共有だか参照だかを述べた日本語訳のある「[詳細
ECMA-262-3](http://alpha.mixi.co.jp/category/ECMA-262-3)」と同じ方が書かれたもので、「[ECMA-262-5
in Detail](http://dmitrysoshnikov.com/ecmascript/es5-chapter-3-1-lexical-
environments-common-theory/#name-binding)」 の中の記述です。

> Think about bindings not as by-reference, but (from C viewpoint) as by-
> pointer (or sometimes — by-sharing) operation. Often it’s also called as a
> special case of by-value where value is an address. Assignment just changes
> (rebinds) the pointer’s value (the address) from one memory block to
> another. And when we assign one variable to another we just copy the address
> of the same object to the second variable. Now two identifiers are said to
> share the one object. From here the name — by-sharing.

参考: [ECMA-262-5 in detail. Chapter 3.2. Lexical environments: ECMAScript
implementation.](http://dmitrysoshnikov.com/ecmascript/es5-chapter-3-1-lexical-
environments-common-theory/#name-binding)

まだ、なんかこう、もやもや感がのこる・・・

それよりも、ここでは変数がオブジェクトを保持することを、"Name-
Binding"とも説明しているのが興味深いですね。変数にオブジェクトを「代入」ではなく「リバインディング」とも言っています。変数名にオブジェクトがバインドされているという概念なんですって。イメージとしては、バインドほうが余計な先入観がなく、説明によいかもしれないと思いました。


CC BY-SA 3.0
2014-12-25T08:11:02.873
2556
2014-12-25T10:30:12.847
2014-12-25T10:30:12.847
4978
4978
2544
answer


<http://www.ecma-international.org/ecma-262/5.1/#sec-11.2.3>

<http://www.ecma-international.org/ecma-262/5.1/#sec-11.2.4>

を見ると、関数に渡る引数はそのリストを評価した際に`GetValue()`をかましていて、いわゆる共有渡しの手順になっていると思うのですが、それでは不足でしょうか。


CC BY-SA 3.0
2014-12-25T09:00:43.410
2558
2014-12-25T09:10:25.400
2014-12-25T09:10:25.400
3313
3313
2544
answer


まず、ご存じだと思いますが JavaScript にはオブジェクトの実体を指し示せる変数は存在しません。あるのはオブジェクトの参照を保持出来る変数です。

[code]

    var a = new Human(); // new した Human 参照を a で保持
    a = new Cat();       // Cat のオブジェクト参照へ切り替える
    
[/code]

**参照** という物は VM 内では一意となります。この一意の値を意味して値渡しという表記されたり記述されたりしているのだと思います。

もちろん、参照されているオブジェクトのプロパティが関数呼び出し時にコピーされる訳ではありませんので、そういう意味では共有渡しと表現される場合もあります。

参照型という表現が出来るならば、それはプリミティブ型と言えますね。

**追記**

<http://dmitrysoshnikov.com/ecmascript/chapter-8-evaluation-strategy/#call-by-
sharing>

> Regardless the fact that the concept of the reference in this case appears,
> this strategy should not be treated as call by reference (though, in this
> case the majority makes a mistake), because the value of the argument is not
> the direct alias, but the copy of the address.

この部分が仕様と思われます。


CC BY-SA 3.0
2014-12-25T09:32:28.830
2560
2014-12-25T09:55:04.733
2014-12-25T09:55:04.733
440
440
2544
answer


まとめると、JSで値が何かの変数にセットされるような書き方がされているときは、
値がコピーされて箱に入れられるようなイメージではなく、新しい名前に値が結び付けられるイメージが良いということでしょうね。

しかし、やはり「値渡し」という言い方をすると、データとしてコピーされて新しいエリアに書かれるようなイメージがあります。Wikipediaの項目を見ても、そのようなイメージで書いてあると思います。  
実際に仕様の細部を実装側で補完して、参照の値渡しなどで実装することも出来そうですが、
あくまで仕様の範囲で語るのであれば、そもそもデータが渡っていくという考え方自体が良くないのかもしれないと思いました。

きっと値という存在に対する名付けの連鎖と捉えるのが一番素直なのかもしれません。  
そうすると、渡すのではなく、むしろ「名前貰い」と言った感じになるのでしょうかね。


CC BY-SA 3.0
2014-12-28T07:22:06.313
2728
2014-12-28T07:22:06.313
5721
2544
answer