Shelley Powers著 武舎広幸+武舎るみ訳 初めてのJavaScript

値呼び出しと参照呼び出し

一般にプログラミング言語で関数(プログラミング言語によってはサブルーチン、プロシージャ等とも呼ばれます)に、引数を渡す方式には、値呼び出しと参照呼び出しがあります(このほかにもありますが、例外的なのでここでは割愛します)。初めてプログラムを作る人にとっては、両者の区別は大変わかりにくいものです。

値呼び出し(call by value)とは

関数に引数を渡すときに、関数の値だけを渡して、記憶している場所は渡さない方法です。値だけが渡され、呼び出した側の変数が記憶されている領域とはまったく別に呼び出された側で使う変数の記憶領域が確保されます。このため、呼び出された側では呼び出した側で使われていた変数にはまったくタッチできません。数の値を入れた変数の値を変更しても、呼び出し側に戻ったときには元の値のママになります。

参照呼び出し(call by reference)とは

参照呼び出しの場合は、関数を呼び出すときに、引数の記憶場所(アドレス)が渡されます。つまり、呼び出し側と呼び出される側の関数で、変数の記憶域が共有されるわけです。したがって、呼び出された側でその変数に対して行った操作は呼び出した側に戻っても、そのまま有効になります。

両者が混在している理由

JavaScriptでは基本データ型(数値、文字列、真偽値)の変数は値呼び出しになり、オブジェクトは参照呼び出しになります。両者が混在していて分かりにくいようにも思えると思いますが、これにはそれなりの理由があるのです。

ひとつには、基本データ型(数値、文字列、真偽値)の変数の記憶領域は、比較的小さいということがあげられます。数値は4バイトとか8バイトとかに固定されていますし、真偽値は1ビットあれば表現できます(実際にはこれも記憶域の管理の都合で、1バイトとか2バイトとか4バイトとか使われることになっていると思いますが)。文字列に必要な記憶域も、その文字列の長さで決まります。したがって、呼び出しのたびに、新たに記憶領域を確保して値をコピーしてから呼び出される側の処理を行ってもJavaScriptの処理系にとってはそれほどの負担にはなりません。

これに対して、オブジェクトは色々なプロパティやメソッドを持ちます。このため、オブジェクトの内容を記憶しておくためにはかなりの容量が必要になります。オブジェクトも「値呼び出し」で呼び出すことにすると、関数の呼び出しのたびに、オブジェクト用の大きな記憶領域を丸ごとコピーして渡してあげなければなりません。これには、ある程度の領域が必要になりますし、コピーを行うのに時間もかかることになります。

もうひとつ、関数にオブジェクトを渡すと言うことは、そのオブジェクトに対して何らかの操作をしたい場合が多いということもあるでしょう。その場合、呼び出された側でオブジェクトに対して行った修正が、そのまま呼び出し側でも有効になっていた方が都合がよいわけです。

基本データ型の変数に変更を加えた場合は、その変更後の値を戻り値として戻して変数に代入すれば、呼び出し側でも変更を反映できます。

そのほかの言語の場合

関数を値呼び出しにするか、参照呼び出しにするかは、プログラミング言語によりさまざまですが、ある意味で一番わかりやすいのはC言語(およびこれを源とする言語)でしょう。C言語の場合は、すべてが値呼び出しになります。ただし、変数のアドレス(記憶域の場所)を渡すことができて、開発者が参照呼び出しにしたい場合はアドレスを渡すことによって参照呼び出しを実現することができます。開発者が自由に選べるわけです(逆に言うと、参照呼び出しの意味を理解していないと参照呼び出しは使えないことになります)。

 

DictJuggler.net

文章に携わる人のための辞書・検索サイトDictJuggler.netオープン
藤本直氏の類語辞典『類語玉手箱』と山岡洋一氏の翻訳者向け訳語辞典『翻訳訳語辞典』を無料公開中!

新刊・近刊

Google Maps Hacks 第2版— 地図検索サービスをもっと活用するテクニック

『初めてのJavaScript』で基本を身につけたあなたにピッタリの1冊。世界規模の地図検索サービスGoogle Mapsを使えば、見るだけでも楽しい地図を、さまざまなテクニックを使って自分で作成することができる!
サポートページで最新情報を提供中。