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

基本

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

また、 JavaScript は大文字と小文字を区別し、また Unicode 文字セットを使用しています。例えば、 Früh という単語 (ドイツ語で "early" という意味) を変数名として使用することができます。

var Früh = "foobar";

ただし、 JavaScript は大文字と小文字を区別するので、 früh という変数は Früh と同じではありません。

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

コメント

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

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

コメントは空白のように扱われ、スクリプトの実効から除外されます。

宣言

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

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

変数

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

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

å や ü といった ISO 8859-1 や Unicode 文字 (詳しくはこのブログ記事を参照) も識別子に使用できます。 Unicode エスケープシーケンスも識別子に使用できます。

Number_hitstemp99_name などは、正しい名前の一例です。

変数の宣言

変数を宣言する方法は3通りあります。

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

変数の評価

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

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

var a;
console.log('変数 a の値は ' + a); // 変数 a の値は undefied

var b;
console.log('変数 b の値は ' + b); // 変数 b の値は undefied

console.log('変数 c の値は ' + c); // キャッチされない ReferenceError: c が定義されていない

let x;
console.log('変数 x の値は ' + x); // 変数 x の値は undefined

console.log('変数 y の値は ' + y); // キャッチされない ReferenceError: y が定義されていない
let y; 

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); // log 0 をコンソールに出力

変数のスコープ

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

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

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

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

if (true) {
  let y = 5;
}
console.log(y);  // ReferenceError: y が定義されていない

変数の巻き上げ

もうひとつ、 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';
})();

上記の例は以下と同様に解釈されます。

/**
 * 例 1
 */
var x;
console.log(x === undefined); // true
x = 3;
 
/**
 * 例 2
 */
var myvar = 'my value';
 
(function() {
  var myvar;
  console.log(myvar); // undefined
  myvar = 'local value';
})();

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

ECMAScript 2015 では、 let (const) はブロックの先頭への巻き上げが行われません。そのため、ブロック内の変数宣言前に変数を参照すると、 ReferenceError になります。変数はブロックの先頭から宣言が実行されるまでの間、「一時的なデッドゾーン」にあります。

console.log(x); // ReferenceError
let x = 3;

関数の巻き上げ

関数については、関数宣言のみ先頭への巻き上げが行われ、関数式は巻き上げが行われません。

/* 関数宣言 */

foo(); // "bar"

function foo() {
  console.log('bar');
}


/* 関数式 */

baz(); // TypeError: baz は関数ではない

var baz = function() {
  console.log('bar2');
};

グローバル変数

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

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

定数

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

const PI = 3.14;

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

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

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

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

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

  // ここには文が来る
}

しかし、定数が代入されたオブジェクトのプロパティは保護されず、以下の文は問題なく実行できます。

const MY_OBJECT = {'key': 'value'};
MY_OBJECT.key = 'otherValue';

また、配列の中身は保護されませんので、以下の文は問題なく実行できます。

const MY_ARRAY = ['HTML','CSS'];
MY_ARRAY.push('JAVASCRIPT');
console.log(MY_ARRAY); //logs ['HTML','CSS','JAVASCRIPT'];

データ構造とデータ型

データ型

最新の ECMAScript 標準では、以下の7つのデータ型が定義されています。

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

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

データ型の変換

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

var answer = 42;

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

answer = 'Thanks for all the fish...';

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進数、2進数で表現することができます。

  • 10進数の整数リテラルは、先頭が0 (ゼロ) ではない一連の数字で構成されます。
  • 先頭に0 (ゼロ) である整数リテラル、または先頭の 0o (または 0O) は8進数であることを示します。8進数では0から7の数字のみが使用できます。
  • 先頭の 0x (または 0X) は、16進数であることを意味します。16進整数は数字 (0から9) と a から f および A から F のアルファベットで構成されます。 (大文字・小文字の違いは値には影響しません。たとえば 0xa = 0xA = 10 and 0xf = 0xF = 15 です。)
  • 先頭の 0b (または 0B) は、2進数であることを表します。2進数整数は 0 と 1 の数字のみで構成されます。

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

0、117、-345 (10進数)
015、0001、-0o77 (8進数)
0x1123、0x00111、-0xF1A7 (16進数)
0b11, 0b0011 and -0b11 (2進数)

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

浮動小数点リテラル

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

  • 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!

拡張オブジェクトリテラル

ES2015 では、オブジェクトリテラルは構築時のプロトタイプの設定に対応するよう拡張され、 foo: foo 形式の短い代入、メソッドの定義、 super の呼び出し、式によるプロパティ名の計算ができるようになりました。同時に、オブジェクトリテラルとクラス定義が近くなり、オブジェクトベースの設計でも同じ利便性の一部から利益を得ることができます。

var obj = {
    // __proto__
    __proto__: theProtoObj,
    // 短い ‘handler: handler’ の形式
    handler,
    // メソッド
    toString() {
     // super の呼び出し
     return 'd ' + super.toString();
    },
    // 計算による (動的な) プロパティ名
    [ 'prop_' + (() => 42)() ]: 42
};

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

var foo = {a: 'alpha', 2: 'two'};
console.log(foo.a);    // alpha
console.log(foo[2]);   // two
//console.log(foo.2);  // エラー: 引数リストの後に ) がない
//console.log(foo[a]); // エラー: a は未定義
console.log(foo['a']); // alpha
console.log(foo['2']); // two

正規表現リテラル

正規表現リテラル (後で詳しく定義) は、スラッシュで囲まれたパターンです。以下は正規表現リテラルの例です。

var re = /ab+c/;

文字列リテラル

文字列リテラルとは、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 が出力される。

ECMAScript 2015 では、テンプレートリテラルも利用することができます。テンプレートリテラルは、二重引用符や単一引用符の代わりに逆引用符 (` `) (grave accent) で囲まれたものです。テンプレート文字列は文字列の構築に糖衣構文が利用できます。これは Prel や Python などの文字列補完機能に似ています。また、文字列の構築をカスタマイズして、インジェクション攻撃を防いだり文字列コンテンツのより高水準のデータ構造を構築したりするためにタグを追加することができます。

// 基本的な文字列リテラルの作成
`In JavaScript '\n' is a line-feed.`

// 複数行の文字列
`In JavaScript template strings can run
 over multiple lines, but double and single
 quoted strings cannot.`

// 文字列補完
var name = 'Bob', time = 'today';
`Hello ${name}, how are you ${time}?`

// 置換や構築を解釈するために使用される HTTP リクエストの接頭辞を構築
POST`http://foo.org/bar?a=${a}&b=${b}
     Content-Type: application/json
     X-Credentials: ${credentials}
     { "foo": ${foo},
       "bar": ${bar}}`(myOnReadyStateChangeHandler);

特に 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 エスケープシーケンスをご覧ください。
\u{XXXXX} Unicode コードポイントエスケープです。例えば \u{2F804} は単純な Unicode エスケープである \uD87E\uDC04 と同じです。

文字のエスケープ

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

バックスラッシュを直前につけることで、引用符を文字列に含めることができます。これは引用符のエスケープと呼ばれます。例えば以下のようにします。

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);   // この文字列は複数行にわたって分解されます。

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

var poem = 
'Roses are red,\n\
Violets are blue.\n\
Sugar is sweet,\n\
and so is foo.'

ECMAScript 2015 ではテンプレートリテラルと呼ばれる新しい種類のリテラルが導入されました。これによって複数行の文字列を含む多数の新機能が利用できるようになりました。

var poem = 
`Roses are red, 
Violets are blue. 
Sugar is sweet, 
and so is foo.` 

関連情報

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

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

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

最終更新者: mfuji09,