多忙な JavaScript 開発者のための ECMAScript 6 ガイド、第 1 回

新しい JavaScript 内での変数宣言およびその他の新仕様の紹介

ECMAScript 6 内でのシンタックス・シュガーによるコア機能の強化

Comments

コンテンツシリーズ

このコンテンツは全4シリーズのパート#です: 多忙な JavaScript 開発者のための ECMAScript 6 ガイド、第 1 回

このシリーズの続きに乞うご期待。

このコンテンツはシリーズの一部分です:多忙な JavaScript 開発者のための ECMAScript 6 ガイド、第 1 回

このシリーズの続きに乞うご期待。

Interactive code: When you see Run at the top of a code sample, you can run the code, check the results, make changes, and run it again.

編集者による注記: このシリーズは、対話式コーディング機能を追加して更新されています。コード・リストに「実行」ボタンがある場合、そのコードを実行して結果を確認し、コードを変更してから再度実行して、その成果を確認できます。

ECMAScript (通称 JavaScript) は、波乱の歴史を辿ってきたスクリプト言語です。当初は、初の Web ブラウザーの 1 つである Netscape Navigator の拡張ポイントとして組み込まれていました。JavaScript という名前は、当時は目新しかった要素を迅速に開発できるようにした Java にちなんで付けられたものですが、JavaScript は Java に劣る言語として長年酷評され続けていました。

1997 年に ECMA として標準化されたことで、JavaScript 言語はある程度の信頼を得ましたが、ECMA 標準最初のメジャー・リリースである ECMAScript 4 により、JavaScript コミュニティーは真っ二つに分かれることになります。一体感を取り戻すべく、「Harmony」と呼ばれる、控え目な、不具合修正を主とした ECMAScript 5 がリリースされました。

けれども最近では、JavaScript は苦境をかいくぐって返り咲いた言語として位置付けられています。Node.js に後押しされて普及するようになった JavaScript は、サーバー・サイドの動力源のような存在になっています。ECMAScript 2015 (ECMAScript 6、ES6 とも呼ばれています) は 2015 年 6 月に正式に標準として採用されてから、着々と主流の標準になりつつあります。2016 年 6 月には、ECMAScript 2016 が仕様として承認されました。

npm レジストリーに含まれるライブラリーやパッケージが最新バージョンへと移行している中、JavaScript 開発者は現在の標準内での新機能を学ぶべき時機が来ています。いくつかの新機能を知れば、間違いなく、コード内でこれらの機能を使い始めたいと思うはずです。

この記事ではまず、コードの柔軟性と効率性に大きな影響をもたらす JavaScript 言語の 6 つの変更を取り上げます。これらの変更のうち、おそらく最も重要な変更は新しい分割代入操作なので、今回と第 2 回で、この分割代入操作を使用するシナリオをいくつか解説したいと思います。

移行戦略

ECMAScript 6 は JavaScript に画期的な変化をもたらしていますが、そのほとんどはシンタックス・シュガーとして分類されます。多くの場合、新しい標準では、コードの処理内容そのものではなく、どのようにしてコードを作成するのかを変えることによって効率性をもたらします。そのような更新は主に、まだ標準化されていないショートカットや回避策など、開発者が既に実践している手法に対処するためのものです。理想的には、新しい言語機能を利用することで、これまでと同じコードをより簡単に、より短時間で作成できるようになりますが、

移行の観点からすると、シンタックス・シュガーに重点を置くと移行を円滑に進められます。新しいことを学ぶよりも、既に持っている知識を広げるほうが、認識的負荷は低くなるからです。けれどもその一方で、同じ結果を得るために、新しい ECMAScript 6 による方法と、従来の方法のいずれかを選べることから、ECMAScript 6 への移行が転換点に達するまでは、混乱することも度々あるでしょう。この変更の多くは柔軟に採用できるようになっているので、段階的かつ柔軟に移行を進めていくという戦略を取ることは可能です。多くの場合、この戦略が最も妥当な移行経路になります。ECMAScript では新機能が山ほど導入されているので、それらの新機能を一度に統合しようとするのは無理な話でしょう。

移行の際に考慮しなければならない問題には、環境の互換性も挙げられます。私たちが厭というほど思い知らされているように、古いブラウザーが使用されなくなるまでには、延々と続くサイクルがあります。このことを明白にする典型例は Internet Explorer です。幸い、クライアント・サイドが 100% ECMAScript 6 に対応していないとしても、「トランスパイラー」を使用すれば ECMAScript 6 ソースを ECMAScript 5 対応のコードに変換できます。とりわけよく使われているトランスパイラーとしては、Traceur および BabelJS の 2 つがあります。

嬉しいことに、サーバー環境の制御も完全に掌握できます。この記事を書いている時点で、最新の Node.js バージョンは新しい標準規格の 92% を実装しています。残りの 8% に含まれる新機能を必要としているのでない限り、Node.js 内で ECMAScript 6 を実行するために特別なセットアップを行う必要はありません。

概要についてはこれで十分でしょう。ここからは、具体的な変更内容を見ていきます。

構文の変更

構文の変更は最も明白であり、場合によっては理解するのも極めて簡単です。ECMAScript 6 では、全体的な JavaScript 構文は大幅に変更されていませんが (セミコロンと波括弧を使用した、ほぼ C ベースの言語のままです)、開発者にとって微妙な違いをもたらす「細部」の多くが整理されています。いくつかの例を見てみましょう。

Unicode 8.0

まず初めに、ECMAScript 6 ではバージョン 8.0 以降の Unicode 標準への適合が要件となっています。Unicode 8.0 には絵文字の文字コード・ポイントがあるため、この要件が意味するとりわけ重要な点は、ECMAScript 対応の環境では笑顔の顔文字を受け入れる必要があるということです。

大半のテキスト・エディターでは、まだ Unicode 8.0 の文字コード・ポイントの一部は直接サポートしていません。そのため、ほとんどの Unicode 文字は文字列リテラル内にエスケープ (例えば、\u{1d306}) として実装することになります。Unicode は識別子にも使用できるため、ECMAScript 6 では変数名についても Unicode エスケープ構文をサポートしています。以下に、一例を示します。

Show result

通常、開発者は Unicode を国際化対応のために使用します。つまり、Unicode は変数識別子としてではなく、文字列リテラル内に現れます。とは言え、コード内で英語以外の言語を使用しようとしている開発者からは、変数識別子におけるこの新しい柔軟性は歓迎されることでしょう。

バイナリーと 8 進数リテラル

整数リテラルとして至るところで使用されている「9」を考えてみてください。リテラル値であること、そしてアラビア文字記数法 (base-10 の 10 進記数法) が優勢を占めていることから、9 は 10 進数リテラルと見なされます。コンピューターは 10 進数の観点からではなく、バイナリー、8 進数、または 16 進数の観点からコードを理解します。ECMAScript ではこれまでずっと、先頭に 0x を使用して示される 16 進数リテラルを使用できるようになっていましたが、ECMAScript 6 内では、リテラルを 0b または 0o から始めることで、それぞれバイナリー (base-2)、8 進数 (base-8) のリテラルを表現できます。例えば、以下の式の値はすべて true なので、ECMAScript 6 内ではいずれのリテラルも同じ値を出力することになります。

Show result

文字列テンプレートと補間

変数メンバーを文字列に挿入する場合、ECMAScript 開発者はこれまでずっと、以下のようにぎこちなく文字列を連結してきました。

Show result

JavaScript 内でバグをもたらす最大の原因というわけではありませんが、この文字列連結の戦略は、コードを読みにくくすることはもちろん、エラーを引き起こしがちです。使いやすさの観点からも、このような文字列連結が原因で、JavaScript は文字列の補間をサポートする言語より遅れを取っています。これらの言語の仲間に入りそびれているという状況に対処すべく、ECMAScript 6 ではバックティック文字列リテラルを導入しています。バックティック文字列リテラルでは、以下のようにバックティック文字 (`) を使用して、文字列の補間をサポートする文字列リテラルを表すことができます。

Show result

{$action}because の間に強制改行を入れているわけは、バックティック付きの文字列も「複数行リテラル」であるためです。つまり、文字列に含まれるホワイトスペースが維持されるため、上記のメッセージは 2 行で表示されます。強制改行により、action の値の後で改行し、2 つのスペースを入れてから (この文字列の 2 行目を字下げするため) メッセージの残りの部分を表示しています。

ECMAScript 6 が既存の単一引用符や二重引用符上でそのまま補間をサポートするのではなく、新種の文字列リテラルを導入しなければならなかったのは、もちろん残念なことです。けれども、こうしなければ、後方互換性にかなりの影響を及ぼすことになっていたでしょう。この点からすると、現在有効なソリューションとしては、バックティックの使用が最善だと思います。いずれ、ほとんどの文字列リテラルがバックティック付きの文字列になると期待されます。

変数宣言: let と const

ECMAScript ではこれまでずっと、プログラマーが変数を宣言せずに使用できるようになっていました。変数を宣言しなければ、その変数は暗黙的にグローバル変数になります。変数を宣言しないことは、好ましくないと考えられていた形です (ただし、この形を「シングルトン」と呼ぶ場合は、パターンであると見なされます)。この問題に対処するために、JavaScript プログラマーは var 宣言スタイルを使用して、変数を使用する前に宣言するようになりました。

他の多くの言語とは異なり、ECMAScript では特定の変数が何度も再宣言されてもエラーが発生することはありませんでした。したがって、従来の ECMAScript では、以下のコードを作成してもエラーは発生しません。

    var msg = "Howdy";
    var msg = "Hello there"; // acceptable, just reassigns

2 番目の宣言がエラーになることは決してありませんでした。上記の例では、元の変数に新しい値が再割り当てされるだけです。このことは、非常にとらえにくいバグの原因となっていて、C/C++/Java/C# 開発者にとってかなり驚くべき状況になっていました。さらに、ECMAScript では、Java にある final や、C# または C++ にある const のような不変の変数を作成するための手段もありませんでした。

ECMAScript 6 は、このすべての問題を解決します。まず、ECMAScript 6 では var を使用するのではなく、再宣言できない let を使用するように提案しています。しかも、letvar とほとんど同じように動作します。

Show result

不変性のニーズには、変数宣言内で const を使用することで対処できます。const を設定して宣言された変数は変更できないためです。

    const message = `This is your message.`;
    message = `This is your second message.`; // ERROR!

const を指定して宣言された変数の値は変更できないとしても、その変数が指すオブジェクトは一定ではないため、変数が変更される可能性があります。

Show result

今後は、最初に const を使用するようにするというのが、私のアドバイスです。変数を変更する必要があることがわかったら、いつでも宣言を let に変えることができます。

ブロック・スコープ

変数宣言について言えば、多くの ECMAScript 開発者にとって意外なことに、宣言された変数は、その変数が宣言された「ブロック」に結び付けられません。宣言された変数が結び付けられるのは関数です。以下に、関数にスコープ設定された変数の例を示します。

Show result

上記の関数は、本質的に、ネストされたループを一度だけ通過することになります。なぜなら、i の 2 番目の「宣言」では値 1 を割り当てるだけであるためです。ただし、あれこれ考え合わせると、この動作はおそらくプログラマーの意図するところではありません。

ECMAScript 6 からは、let および const を使用して宣言された変数のスコープはブロックに設定されるため、変数がそのスコープを出るのは、関数が終了した時点ではなく、現在の式のブロックが終わった時点です。上記のコードを、var ではなく let を使用して作成し直すと、期待される動作になります。

Show result

大局的な見地から言えば、ブロック・スコープとは、let および const を使用して宣言された変数が他のあらゆる C ベースの言語の場合と同じように動作することを意味するにすぎません。この変更は、ECMAScript が今までどうにかやってきた、むしろ驚くべき方法に対する改善です。

分割代入

変数宣言に関する変更がもう 1 つあります。ECMAScript 6 に含まれている最も重要な更新の 1 つとして挙げられるこの変更は、分割代入です。分割代入では、単一の配列またはオブジェクトからデータを取り出して、複数の変数に代入することができます。基本的に、この処理は、配列またはオブジェクトを、それを構成する複数の部分に「分割」するというものです。

分割代入は、言葉で説明するよりも実例で説明したほうが理解しやすいでしょう。例えば、['Ted', 'Jenni', 'Athen'] のような配列がある場合、分割代入形式の変数宣言を使用すれば、配列を個々の配列要素に分解して、それぞれの要素を個別の変数に代入することができます。

Show result

変数宣言を囲む配列の括弧に注目してください。この括弧により、ECMAScript は等号の右側の配列が対象であることを理解します。宣言された変数の数より多くの要素が配列に含まれている場合は、配列の残りの要素がドロップされるだけです (当然、値は配列に残ります。配列の値は変数にコピーされるので、元の配列は影響されないまま維持されます)。配列に含まれる要素が、宣言された変数の数より少ない場合、ECMAScript は値が代入されない残りの変数に値「undefined」を取り込みます。

多くの点で、分割代入の配列形式は、古い形式の同じ操作に対する単なるシンタックス・シュガーでしかありません。

    var ted = names[0];
    var jenni = names[1];
    var athen = names[2];

分割代入バージョンのほうが断じて短く、ほぼ間違いなく表現力がより豊かになります。

オブジェクトでの分割代入

分割代入が最も役立つ 1 つの例としては、以下のような正規表現の解析からの値の抽出が挙げられます。

Show result

オブジェクトに対しても、上記と同じような分割代入を適用できます。例えば、単純なオブジェクトには以下のように分割代入を適用できます。

Show result

この特定の例では、オブジェクトに対して分割代入が行われています。変数は、右側のオブジェクト内で見つかった、その変数の名前に対応する要素に結び付けられます。つまり、変数を逆の順序で作成したとしても、x の値は point.x から受け取り、y の値は point.y から受け取ることになります。

Show result

何らかの理由からオブジェクトのフィールド名が一致していなくても構わないという場合は、フィールド・スタイルの構文を使用して、左側で一致させる名前を指定し、右側で宣言された変数の実際の名前を指定して、フィールドの名前を変更することができます。

Show result

この方法に従うと、オブジェクトを分割代入する際の変数の命名をより細かく制御できます。

複数のレベルで分割代入を行うことも可能です。例えば、四角形は通常、2 つのポイントとして表現されます。四角形の 4 つの値を抽出する必要があるとしたら、2 つの x/y ペアを 4 つの別個の変数に取り込むという方法で対処できます。

Show result

上記の例で、「lowerLeft」と「upperRight」は実際の変数ではありません。この 2 つはプレースホルダーであり、分割代入対象オブジェクト内の対応する名前を持つフィールドと、下位フィールドをどのように結び付けるかを示すためにあります。この例で実際に導入される変数は、llxllyurx、および ury のみです。

分割代入についての説明は、今のところはこれで十分ですが、終わったわけではありません。今後の記事で、この新しい構文がメソッド・パラメーター内でどのように機能するかを説明します。

まとめ

ECMAScript 6 に用意されている新仕様の説明はまだ序盤ですが、この言語がその前身とは異なっていることは既に理解できたはずです。この最新エディションの仕様は、新たな成熟度を示していて、これまで 10 年近く、開発者を苦しめていた欠陥が修正されています。

ECMAScript 6 に含まれている変更の一部は、すぐに取り入れて簡単に適用できます。例えば、letconst は、var に代えて簡単に使い始めることができます。その一方で、バックティック文字列構文をはじめ、統合するまでに時間がかかる変更もあります。けれどもありがたいことに、すべての ECMAScript エンジンは後方互換性を備えているので、まだ時間は残されています。

時間と言えば、今回の記事にはもう時間が残されていません。ECMAScript 6 での関数の更新について探る準備ができたら、第 2 回を読んでください。


ダウンロード可能なリソース


関連トピック


コメント

コメントを登録するにはサインインあるいは登録してください。

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Web development
ArticleID=1040100
ArticleTitle=多忙な JavaScript 開発者のための ECMAScript 6 ガイド、第 1 回: 新しい JavaScript 内での変数宣言およびその他の新仕様の紹介
publish-date=07132017