文法とデータ型

この記事は技術レビューを必要としています。ぜひご協力ください

この記事は編集レビューを必要としています。ぜひご協力ください

本章では JavaScript の基本構文、変数宣言、データ型とリテラルについて説明します。

基本

JavaScript は Java から構文の多くを取り入れていますが、Awk や Perl、そして Python からも影響を受けています。

また、JavaScript はケースセンシティブ、つまり大文字と小文字を区別し、また Unicode を使用しています。

JavaScript では、命令は (statement) と呼ばれ、セミコロン (;) によって区切られています。スペース、タブ文字、改行文字は「空白文字」と呼ばれます。JavaScript のソーステキストは左から右にスキャンされ、トークン、制御文字、行末、コメントや空白文字といった入力要素に変換されます。また ECMAScript ではキーワードやリテラルが定義されていて、また行の終わりにセミコロンを自動で挿入するルール (ASI) があります。ですが、副作用を防ぐため、常に文の終わりにはセミコロンを入れるのをおすすめします。さらなる情報は、JavaScript の字句文法についての詳細なリファレンスをご覧ください。

コメント

コメントの構文は C++ やその他の多くの言語と一緒です :

// 一行のコメント
 
/* もっと長い、
   複数行からなるコメント
 */
 
/* ただし、コメントは /* ネストできません */ SyntaxError となります */

宣言

JavaScript には宣言を行う方法が 3 種類あります。

var
変数を宣言し、ある値に初期化することもできる。
let
ブロックスコープのローカル変数を宣言し、ある値に初期化することもできる。
const
読み取り専用の名前付き定数を宣言する。

変数

アプリケーションで値を表す名前として、変数を使用します。変数の名前は識別子とも呼ばれ、一定のルールに従わなくてはなりません。

JavaScript の識別子は必ず文字、アンダースコア (_)、あるいはドル記号 ($) から始まらなくてはなりません。続く文字には数字 (0-9) も使用できます。JavaScript は大文字・小文字を区別するため、使用できる文字には "A" から "Z" (大文字)に加えて "a" から "z" (小文字)も含まれます。

JavaScript 1.5 より、å や ü といった ISO 8859-1 や Unicode 文字も識別子に使用できます。\uXXXX 形式のUnicode エスケープシーケンスも識別子に使用できます。

Number_hitstemp99_name などが、ルールに即した変数名の一例です。

変数の宣言

変数を宣言する方法には 3 種類あります :

  • キーワード var を使う。例えば、var x = 42 。 この構文はローカル変数とグローバル変数、両方の宣言に利用できます。
  • 単純に変数に値を代入する。例えば、x = 42 。この方法では常にグローバル変数として宣言されます。Strict モード の JavaScript の場合は警告が出されます。この方法は使用すべきではありません。
  • キーワード let を使う。例えば、 let y = 13 。この構文はブロックスコープのローカル変数を宣言することができます。以下にある変数スコープをご覧ください。

変数の評価

varlet 文を使用して初期値なしで宣言された変数は、undefined の値をとります。

未宣言の変数にアクセスしようとすると、ReferenceError 例外が発生します :

var a;
console.log("変数 a の値は " + a); // "変数 a の値は undefined" とログに出力される
console.log("変数 b の値は " + b); // ReferenceError 例外が発生

undefined を使って変数に値が入っているかを確認できます。以下のコードでは変数 input に値が代入されておらず、if 文は true と評価されます。

var input;
if(input === undefined){
  doThis();
} else {
  doThat();
}

undefined は真偽値のコンテキストで使用されると false としてふるまいます。例えば以下のコードでは、myArray の要素が未定義であるために関数 myFunction が実行されます :

var myArray = [];
if (!myArray[0]) myFunction(); 

undefined は数値のコンテキストで使用されると NaN に変換されます。

var a;
a + 2;  // NaN と評価される

null を評価する際、数値のコンテキストでは null 値は 0 としてふるまいます。また真偽値のコンテキストでは false としてふるまいます。例えば :

var n = null;
console.log(n * 32); // Will log 0 to the console

変数のスコープ

変数を関数の外側で宣言すると、その変数はその文書のどのコードからも使用できるようになるため、グローバル(大域)変数と呼ばれます。変数を関数の内部で宣言すると、その変数はその関数の中でしか使用できないため、ローカル(局所)変数と呼ばれます。

ECMAScript 6 以前の JavaScript にはブロック文のスコープがありません。正確に言えば、ブロック内で宣言した変数はブロックを内包している関数(あるいはグローバルスコープ)に対して局所化されます。例えば以下のコードでは、x のスコープは x の宣言を含む関数(あるいはグローバルコンテキスト)であり、ブロック、すなわち if 文ではないので 5 が出力されます。

if (true) {
  var x = 5;
}
console.log(x);

このふるまいは ECMAScript 6 によって導入された let を使うことで変わります。

if (true) {
  let y = 5;
}
console.log(y);  // ReferenceError: y is not defined

変数の巻き上げ

もうひとつ、JavaScript の変数にまつわる独特な点として、例外を発生させることなく後に宣言した変数を参照できる点が挙げられます。この考え方は巻き上げとして知られています。JavaScript の変数は関数や文の先頭まで、ある意味「巻き上げられ」、持ち上げられます。一方、巻き上げられない変数は undefined 値を返します。そのため、その変数を使用したり参照した後に宣言や初期化を行っても、依然として undefined が返されます。

/**
 * 例 1
 */
console.log(x === undefined); // "true" が記録される
var x = 3;

/**
 * 例 2
 */
// undefined 値が返される
var myvar = "my value";

(function() {
  console.log(myvar); // undefined
  var myvar = "local value";
})();

前出の例 2 は以下と同様に解釈されます :

var myvar = "my value";

(function() {
  var myvar;
  console.log(myvar); // undefined
  myvar = "local value";
})();

巻き上げにより、関数内にあるすべての var 文は関数内で可能な限り先頭に近い位置に置くべきです。これはコードの明確さを高める最善の方法です。

グローバル変数

グローバル変数は、実際にはグローバルオブジェクトのプロパティです。Web ページでのグローバルオブジェクトは window になります、そのため window.variable という構文を用いてグローバル変数のセットやアクセスができます。

したがって、あるウィンドウやフレームで宣言したグローバル変数は、そのウィンドウやフレームの名前を指定することで別のウィンドウやフレームからアクセスできます。例えば phoneNumber 変数を FRAMESET 文書内で宣言すると、子フレームから parent.phoneNumber としてその変数を参照できます。

定数

const キーワードを用いて、読み取り専用の名前付き定数を作成できます。定数識別子の構文は変数識別子の構文と同じです。識別子は文字、アンダースコア、ドル記号から始めなくてはならず、アルファベット、数値、アンダースコアを含めることができます。

const prefix = '212';

定数は代入によって値を変えたり、スクリプト実行中に再宣言したりすることはできません。定数はある値に初期化しなければなりません。

定数のスコープルールは、let によるブロックスコープ変数と同じです。const キーワードを省略すると、その識別子は変数を表すとみなされます。

同一スコープ内で、関数や変数と同じ名前の定数を宣言することはできません。例えば :

// この場合、エラーが発生
function f() {};
const f = 5;

// この場合もエラーが発生
function f() {
  const g = 5;
  var g;

  // ここには文が来る
}

データ構造とデータ型

データ型

最新の ECMAScript 標準化では以下の 7 つの型が定義されています :

  • 6 つのデータ型はプリミティブ型です:
    • 真偽値 (Boolean)true または false.
    • null。null 値を意味する特殊なキーワードです。JavaScript は大文字・小文字を区別するため、nullNullNULL などとは異なります。
    • undefined。値が未定義のトップレベルプロパティ。
    • 数値 (Number)423.14159 など。
    • 文字列 (String)。 "Howdy" など。
    • シンボル (Symbol)(ECMAScript 6 の新機能)。 インスタンスが固有で不変となるデータ型。
  • そして オブジェクト (Object)

このようにデータ型の種類は比較的少ないですが、アプリケーションで便利な関数を実行することができます。整数と実数の間に明確な違いはありません。オブジェクト関数も言語において基本的な要素です。オブジェクトは値を収める名前付きコンテナとして、関数はアプリケーションを実行可能にする手続きとして考えることができます。

データ型の変換

JavaScript は動的型付け言語です。そのため変数宣言時にデータ型を指定する必要がなく、またスクリプト実行時に必要に応じてデータ型が自動的に変換されます。例えば以下のように変数を定義したとします :

var answer = 42;

その後、同じ変数に文字列を代入できます :

answer = "いままで魚をありがとう...";

JavaScript は動的型付けであるため、この代入時にエラーメッセージは出ません。

数値と文字列を + 演算子で結合する式では、JavaScript は数値を文字列に変換します。以下の式を見てみましょう :

x = "答えは " + 42 // "答えは 42" を返す
y = 42 + " が答え" // "42 が答え" を返す

それ以外の演算子がある式では、JavaScript は数値を文字列に変換しません。例えば :

"37" - 7 // 30 を返す
"37" + 7 // "377" を返す

文字列から数値への変換

数値を表す値が文字列として記憶されている場合、それを変換する手段があります。

parseInt は整数のみを返すので、小数は切り捨てられます。さらに、parseInt を使う最も良い方法は、常に基数パラメータを含めるようにすることです。基数パラメータは使用されている基数法を指定するのに使われます。

文字列から数値を取り出す代替手段は、+ (単項プラス)演算子を使う方法です。

"1.1" + "1.1" = "1.11.1"
(+"1.1") + (+"1.1") = 2.2
// 注記 : 括弧は明確さのために追加したもので、必須ではありません

リテラル

JavaScript では値の表現にリテラルを使います。これらは固定値であり変数ではなく、スクリプト中に直接記述します。本章では、以下のリテラルについて説明します :

配列リテラル

配列リテラルとは、0個以上の式のリストであり、各々の式は配列の要素を表し、角括弧 ([]) で括られているもののことです。配列リテラルを用いて配列を作成すると、指定された値が要素として初期化され、また配列の長さは指定された引数の個数に設定されます。

以下の例では3つの要素を持ち、長さが 3 の配列 coffees を作成します :

var coffees = ["French Roast", "Colombian", "Kona"];

注記 : 配列リテラルはオブジェクト初期化子の一種です。オブジェクト初期化子の使用を参照してください。

トップレベルのスクリプト内でリテラルを用いて配列を作成した場合、JavaScript は配列リテラルを含む式を評価するたびに配列を解釈します。さらに関数内で使用されたリテラルは、関数が呼び出されるたびに生成されます。

配列リテラルは Array オブジェクトでもあります。Array オブジェクトの詳細は Array オブジェクトインデックス付きコレクションをご覧ください。

配列リテラルでの余分なコンマ

配列リテラルですべての要素を指定する必要はありません。立て続けに 2 つのコンマを置くと、配列は未指定の要素を undefined として作成します。次の例では fish という配列を作成します :

var fish = ["Lion", , "Angel"];

この配列は、値を持つ要素を 2 つと空の要素を 1 つ持っています (fish[0] は "Lion"、fish[1]undefinedfish[2] は "Angel")。

要素のリストの最後にコンマをつけた場合、そのコンマは無視されます。次の例では、配列の長さは 3 です。myList[3] は存在しません。リスト内の他のコンマはすべて、新しい要素を示します。

注記 : 末尾のコンマは古いブラウザでエラーを引き起こす場合があるので、取り除いておくのが最善の手段です。

var myList = ['home', , 'school', ];

次の例では、配列の長さは 4 です。myList[0]myList[2] が抜けています。

var myList = [ , 'home', , 'school'];

次の例では、配列の長さは 4 です。myList[1]myList[3] が抜けています。最後のコンマのみが無視されます。

var myList = ['home', , 'school', , ];

自身のコードを記述する際に余分なコンマの動作を理解することは、言語としての JavaScript を理解するために重要です。欠落している要素を明示的に undefined として宣言すれば、コードの明確さや保守性が高まります。

真偽値リテラル

真偽値型は 2 つのリテラル値、truefalse があります。

プリミティブ型の真偽値である truefalse と、Boolean オブジェクトの true や false という値とを混同してはいけません。Boolean オブジェクトは、プリミティブな真偽値型のラッパです。詳細は Boolean オブジェクトを参照してください。

整数

整数は 10 進数、16 進数、8 進数で表現可能です。

  • 10 進整数リテラルは、先頭が 0(ゼロ)ではない一連の数字で構成されます。
  • 整数リテラルにおいて 8 進数を表す方法は現在 2 種類あります。また、8 進整数は 0 から 7 までの数字のみで構成されます。
    • 先頭に 0(ゼロ)がある整数リテラルは 8 進数であることを意味します。このリテラル記法は ECMAScript 3 の標準仕様からは削除され、現在は後方互換性保持の目的で実装されています。また ECMAScript 5 から実装された strict モードでこのリテラルを使用すると構文エラーとなります。
    • 先頭に 0o(ゼロと小文字のオー)、または 0O(ゼロと大文字のオー)がある整数リテラルも、8 進数であることを意味します。このリテラル記法は ECMAScript 6 によって標準化され、各環境に実装されつつあります。
  • 先頭の 0x (または 0X)は、16 進数であることを意味します。16 進整数は数字 (0 から 9) と a から f および A から F のアルファベットで構成されます。
  • 先頭の 0b (または 0B)は、2 進数であることを表します。2 進数整数は 0 と 1 の数字のみで構成されます。

整数リテラルの例は以下のようになります :

0、117、-345 (10進数)
015、0001、-077 (8進数、古い方法) 
0o15、0o001、-0o77 (8進数、新しい方法)
0x1123、0x00111、-0xF1A7 (16進数)

さらなる情報は、字句構文リファレンスの数値リテラルをご覧ください。

浮動小数点リテラル

浮動小数点リテラルは、以下の部品で構成されます :

  • 10進整数部 ("+" や "-" の符号が先行してもよい)
  • 小数点 (".")
  • 小数部(10進数)
  • 指数部

指数部は、"e" または "E" の後に、符号("+" または "-")が先行できる整数が続く形になります。浮動小数点数リテラルは少なくとも 1 つの数字と、小数点もしくは "e" (または "E")が必要です。

より簡潔に書けば、次の形式になります :

[digits][.digits][(E|e)[(+|-)]digits]

例えば :

3.1415926
-.123456789
-3.1E+12
.1e-23

オブジェクトリテラル

オブジェクトリテラルとは、プロパティ名とそれに関連付けられたオブジェクトの値との 0 個以上の組が波括弧 ({}) で囲まれたもので作られたリストです。オブジェクトリテラルを文の先頭で使わないようにしてください。{ がブロックの始まりと解釈されるため、エラーや予期せぬ動作を引き起こすことになります。

以下にオブジェクトリテラルの例を示します。car オブジェクトの最初の要素には myCar プロパティが定義され、新規文字列 "Saturn" が割り当てられています。2 番目の要素、getCar プロパティには関数 (carTypes("Honda")) によって呼び出された結果が即座に割り当てられます。3 番目の要素、 special プロパティには既存の変数 (sales) が使われています。

var sales = "Toyota";

function carTypes(name) {
  if (name == "Honda") {
    return name;
  } else {
    return "Sorry, we don't sell " + name + ".";
  }
}

var car = { myCar: "Saturn", getCar: carTypes("Honda"), special: sales };

console.log(car.myCar);   // Saturn
console.log(car.getCar);  // Honda
console.log(car.special); // Toyota 

さらに、数値リテラルや文字列リテラルをプロパティ名に使用したり、オブジェクトを別のオブジェクトの入れ子にすることができます。以下の例では、これらの機能を使用しています。

var car = { manyCars: {a: "Saab", "b": "Jeep"}, 7: "Mazda" };

console.log(car.manyCars.b); // Jeep
console.log(car[7]); // Mazda

オブジェクトのプロパティには空の文字列を含むあらゆる文字列が使えます。もしプロパティ名が JavaScript で有効な識別子か数値でなければ、引用符で囲む必要があります。有効でない識別子によるプロパティ名にはドット演算子 (.) を使ってアクセスできませんが、配列のような表記法 ("[]") でアクセス、設定ができます。

var unusualPropertyNames = {
  "": "An empty string",
  "!": "Bang!"
}
console.log(unusualPropertyNames."");   // "SyntaxError: Unexpected string" が発生
console.log(unusualPropertyNames[""]);  // アクセスが成功、"An empty string" とログに表示される
console.log(unusualPropertyNames.!);    // "SyntaxError: Unexpected token !" が発生
console.log(unusualPropertyNames["!"]); // アクセスが成功、"Bang!" とログに表示される

以下のことに注意してください :

var foo = {a: "alpha", 2: "two"};
console.log(foo.a);    // alpha
console.log(foo[2]);   // two
//console.log(foo.2);  // Error: missing ) after argument list
//console.log(foo[a]); // Error: a is not defined
console.log(foo["a"]); // alpha
console.log(foo["2"]); // two

文字列リテラル

文字列リテラルとは、0 個以上の文字を二重引用符 (") または単一引用符 (') でくくったものです。文字列は同じ種類の引用符でくくらなければなりません。つまり、どちらも単一引用符にするか、またはどちらも二重引用符にします。以下が文字列リテラルの例です :

"foo"
'bar'
"1234"
"one line \n another line"
"John's cat"

文字列リテラルを持つ値は、String オブジェクトのあらゆるメソッドを呼び出すことができます。JavaScript は自動的に文字列リテラルを一時的な String オブジェクトに変換し、メソッドを呼び出して、その後一時的に作られた String オブジェクトを破棄します。String.length プロパティを文字列リテラルで用いることもできます :

console.log("John's cat".length) 
// 空白文字を含む文字列の文字の数を出力する。 
// この場合は 10 が出力される。

特に String オブジェクトを使う必要がない場合は、文字列リテラルを使うようにしてください。詳細は、String オブジェクトをご覧ください。

文字列での特殊文字の使用

通常の文字に加えて、文字列では特殊文字も使用できます。次の例をご覧ください。

"one line \n another line"

ここで、JavaScript の文字列で使用できる特殊文字の表を示します。

表 : JavaScript の特殊文字
文字 意味
\0 ヌル文字
\b バックスペース
\f 改ページ
\n 改行
\r 復帰
\t タブ
\v 垂直タブ
\' アポストロフィまたは単一引用符
\" 二重引用符
\\ バックスラッシュ (\)
\XXX 0 から 377 までの 3 桁の 8 進数 XXX で指定された、Latin-1 エンコーディングの文字。例えば、\251 は著作権記号を示します。
\xXX 00 から FF までの 2 桁の 16 進数 XX で指定された、Latin-1 エンコーディングの文字。例えば、\xA9 は著作権記号を示します。
\uXXXX 4 桁の 16 進数 XXXX で指定された Unicode 文字。例えば、\u00A9 は著作権記号を示します。Unicode エスケープシーケンスをご覧ください。

文字のエスケープ

上記の表に掲載されていない文字は直前にバックスラッシュをつけても無視されますが、こうした使い方は非推奨なので使用を避けるべきです。

バックスラッシュを直前につけることで、引用符を文字列に含めることができます。これを「引用符をエスケープする」と言います。例えば :

var quote = "He read \"The Cremation of Sam McGee\" by R.W. Service.";
console.log(quote);

この結果は次のようになります :

He read "The Cremation of Sam McGee" by R.W. Service.

文字列にバックスラッシュそのものを含めるには、バックスラッシュのエスケープが必要です。例えば、文字列に c:\temp というファイルパスを代入するには、以下のようにします :

var home = "c:\\temp";

改行の直前にバックスラッシュを置くことで、改行をエスケープすることもできます。バックスラッシュと改行の両方が、文字列の値から取り除かれます。

var str = "this string \
is broken \
across multiple\
lines."
console.log(str);   // this string is broken across multiplelines.

JavaScript に "ヒアドキュメント" 構文はありませんが、各行の末尾に改行のエスケープ表記とエスケープした改行を置くことで似たことができます :

var poem = 
"Roses are red,\n\
Violets are blue.\n\
I'm schizophrenic,\n\
And so am I."

さらなる情報について

本章では宣言とデータ型についての基本文法に重点を置いています。JavaScript の言語構成についてより詳しく知りたければ、当ガイドの以下に挙げた章をご覧ください :

次章では、制御フローの構造とエラー処理について見ていきます。

ドキュメントのタグと貢献者

タグ: 
 このページの貢献者: pooh5puuu, Aika, x2357, teoli, ethertank, akiroom, yyss
 最終更新者: pooh5puuu,