第3回 変数の宣言とスコープ連載:Ajax時代のJavaScriptプログラミング再入門(1/4 ページ)

暗黙的なデータ型、2種類のスコープなど、混乱しやすいポイントを中心にJavaScriptの「変数」についてまとめる。

» 2007年08月21日 00時00分 公開
連載:Ajax時代のJavaScriptプログラミング再入門
Insider.NET

 

「連載:Ajax時代のJavaScriptプログラミング再入門」のインデックス

連載目次

 JavaScriptが、いま注目を浴びている。

 長い冷遇の時代を経ながらも、Ajaxという技術の登場とも相まって、JavaScriptの価値はいままた確実に見直されつつある。その過去の凋落と近年の華々しい脚光は、「復権」と呼んでもよいかもしれない。

 本連載は、JavaScript復権のいまこの時代に求められる、JavaScriptという言語への理解を再確認しようというものだ。その連載、第3回となる今回扱うテーマは、「変数」である。どのような言語においても同様であるが、コード上で値を入力し、処理した結果を格納し、また、ほかへと引き渡すすべての基本となるのが変数だ。プログラミング言語を理解するうえにおいて、変数の理解は欠かせない。そして、それはJavaScriptの世界においても同様だ。

 本稿では、JavaScriptにおける変数のデータ型に始まり、そのスコープ(有効範囲)の概念、そして、初学者にとってはやや分かりにくい「クロージャ」について解説する。

変数とデータ型

 JavaScriptは、変数の型を意識する必要のない言語である。しかし、これは変数を使用する際にデータ型を指定する必要がない(指定できない)というだけであって、JavaScriptがデータ型そのものを持たないというわけではない。JavaScriptの世界では、プログラマがそれと指定しなくても、代入された値に応じて、適切なデータ型が自動的に割り当てられるというだけなのである。

 そのため、基本的には開発者がデータ型を意識しなければならない局面というのはそれほど多くはないのだが、それでもまったく意識しなくてもよいというわけではない。まずは、JavaScriptで利用可能なデータ型を見てみることにしよう。

データ型 基本型 数値型(number)
文字列型(string)
真偽型(boolean)
特殊型(null/undefined)
参照型 配列(array)
オブジェクト(object)
関数(function)
JavaScriptで利用可能なデータ型の分類
JavaScriptのデータ型は大きく「基本型」と「参照型」に分類できる。

 この表を見ても分かるように、JavaScriptのデータ型は大きく「基本型」と「参照型」に分類でき、値がいずれの型に属するかによって振る舞いも異なるので、要注意だ。基本型が変数に対して直接に値を格納するのに対して、参照型ではその参照値が格納される。参照値とは、値を実際に格納しているメモリ上のアドレス(ポインタ)のことである。

 この性質の違いによってどのようなことが起こるのか――それぞれの特徴を理解するために、以下のリスト1、リスト2に注目してみることにしよう。

var x = 10;
var y = x; [A]

x = 20; [B]
window.alert(y); // 10(コピーされた値を表示) [C]

リスト1 基本型の挙動を確認
[C]のコメントにある「10」はwindow.alert関数によりメッセージボックスに表示される値を示している(これ以降のリストでも同様)。

var x = [0, 1, 2]; // 配列
var y = x; [D]

x[0] = 10; // 配列の先頭の要素を書き換え [E]
window.alert(y); // 10,1,2(参照元の値を表示) [F]

リスト2 参照型の挙動を確認

 基本型(リスト1)の挙動については、特に問題ないだろう。基本型においては、値は変数に直接に格納されるので、[A]で変数xの値を変数yに引き渡す場合にも、値はコピーされる(値渡し)。つまり、[B]でコピー元の変数xの値を変更しても、変数xとyとはまったくの別物なので、[C]ではコピーされた値である「10」を取得できるというわけだ。

 しかし、参照型ではそうはいかない。参照型においては、変数に格納されるのは「値の格納先」(参照)だけであるので、リスト2の[D]で変数xの値を変数yに引き渡す場合にも、参照が引き渡されるにすぎない(参照渡し)。この時点で、変数xとyとは同じアドレスに格納された同じ値を見ている形になるわけだ。

 従って、[E]で変数xに対して変更を加えた場合にも、実際には参照先の値を変更することになるので、同じアドレスを参照している変数yの側にも変更が影響することになる。果たして、[F]で変数yを参照すると、変数xに加えられた変更が変数yにも反映されていることを確認できる。

 基本型と参照型との区別については、後のスコープの解説でも再度登場するので、両者の区別をここで確実に押さえておいていただきたい。

[参考]varキーワード

 varキーワードは、変数を宣言するための命令である。

 厳密には、JavaScriptでは変数の宣言は任意であるし、varキーワードを使わずに「x = 10;」のように値を直接割り当てても構わない(その場合にも、自動的に変数が生成される)。が、後節で述べるような理由でお勧めはできない。

 まずは無条件に、JavaScriptの変数はvar命令で宣言すると覚えておくことを強くお勧めしたい。


■データ型の明示的な変換

 繰り返しであるが、JavaScriptという言語は型についてとかく寛容な言語である。例えば、以下のようなコードも何ら問題なく動作する。

var x = 10;  // 数値型
var y = "2"; // 文字列型

window.alert(x * y); // 20

リスト3 *演算子を用いた数値と文字列の演算

 このようなコードでも「*演算子」の前後は数値であろうと推測し、JavaScriptが文字列(変数y)を自動的に数値に変換したうえで演算を行ってくれるわけだ。これは、JavaScriptのスクリプト言語としてのシンプルさを支える特徴である。

 しかし、このような寛容さは時として思わぬ不具合をもたらす一因にもなる。次に、以下のようなコードを見てみよう。

var x = 10;  // 数値型
var y = "2"; // 文字列型

window.alert(x + y); // 表示結果は?

リスト4 +演算子を用いた数値と文字列の演算

 ここで、多くの方は結果として「12」が返されることを期待するはずだ。しかし、リスト4の結果は「102」。オペランドの片方が文字列である場合、「+演算子」は(加算演算子ではなく)文字列連結演算子と見なされ、変数xとyとが文字列として連結されることになる。

 このように、型に対する寛容さは、時として予期せぬ結果を得ることにもなるわけだ。そこで、JavaScriptではデータ型を明示的に変換する方法も提供している。データ型の明示的な変換にはいくつかの方法があるが、ここでは代表的な例として、(1)組み込みオブジェクトのコンストラクタを利用する方法と、(2)「+演算子」「−演算子」を利用する方法について紹介しておくことにする。

(1)組み込みオブジェクトのコンストラクタ

 連載第1回でも触れたように、JavaScriptではString、Number、Booleanのような組み込みオブジェクトが用意されている。これらのコンストラクタを呼び出すことで、明示的に対応する型に値を変換することができる。

 例えば、以下のリスト5は、リスト4における変数yをNumberオブジェクトに格納することで、明示的に数値に変換している例だ。果たして、今度は値「10」と値「2」とがそれぞれ数値であるため、+演算子は加算演算子と見なされ、結果も「12」を返す。

var x = 10;
var y = "2";
var yy = new Number(y); [A]

window.alert(x + yy); // 12

リスト5 組み込みオブジェクトのコンストラクタを用いたデータ型の明示的な変換

 ちなみに、これらコンストラクタは関数として呼び出すことも可能だ。つまり、[A]の部分は、

var yy = Number(y);


のように書き換えても構わない。

(2)「+演算子」「−演算子」

 数値⇔文字列間の変換を行うならば、+演算子あるいは「−演算子」を利用した明示的な変換を行うことも可能だ。

 以下のリスト6は、変数x(数値)、変数y(文字列)をそれぞれ文字列、数値に変換する例である。なお、リスト内で使用しているtypeof演算子は、指定された変数の内部データ型を文字列で返すためのものである。

var x = 10;
window.alert(typeof x); // number

var xx = x + ""; [A]
window.alert(typeof xx); // string

var y = "2";
window.alert(typeof y); // string

var yy = y - 0; [B]
window.alert(typeof yy); // number

リスト6 文字列xを数値に、数値yを文字列に変換する例

 先ほども述べたように、+演算子は与えられたオペランドのいずれかが文字列である場合に、もう片方も文字列に自動変換したうえで文字列連結を行うという性質を持っている。[A]ではその性質を利用して、数値xを強制的に文字列に変換しているというわけだ。

 一方、[B]では−演算子を利用した「文字列→数値」変換の例だ。−演算子では与えられたオペランドのいずれかが数値である場合に、もう片方も数値に自動変換したうえで減算処理を行う。ここではその性質を利用して、文字列yを強制的に数値に変換している。

 ちなみに、ここで「0」を減算して変換できるならば、「0」を加算しても「文字列→数値」変換を行えるのではないかと思われる方もいるかもしれない。しかし、前述したように、これは不可である。しつこいようであるが、+演算子は加算演算子と文字列連結演算子という2つの意味を持っている。オペランドの片方が文字列である場合、+演算子は(加算演算子ではなく)文字列連結演算子として解釈されてしまうのだ。この点、やや混乱しやすいポイントでもあるので、注意していただきたい。

       1|2|3|4 次のページへ

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。