Default Parameter
Default Parameters、関数への引数に対して未定義時(undefined)の初期値を与えることが可能となる構文です。関数の呼び出しに引数が省略された場合でも、初期値が設定されることでundefined erorrを防ぐことができます。
"use strict"; function foo(name, version=6){ console.log(name + version); } foo("ES"); // ES6
この例では変数versionに対して初期値6が設定されています。bableコマンドでトランスパイルしたコードでは、arguments[1]が未定義(undefined)であった場合、初期値の6が設定されるようなES5のコードに変換されます。
"use strict"; function foo(name) { var version = arguments[1] === undefined ? 6 : arguments[1]; console.log(name + version); } foo("ES"); // ES6
なお、あくまで未定義(undefined)に対しての初期値なので、nullやfalseなどを指定した場合は初期値は適用されません。
function foo(name="ES", version){ console.log(name + version); } foo("ES", null); // ESnull
Rest Parameter
Rest Parameter関数の引数を可変の配列(Array)として受け取れるようになります。呼び出し時に引数が1つも指定されなくてもデフォルトで空のArrayが設定されます。
function foo(...args) { console.log(args); } foo(1,'2',[3,4,5]); // [1, '2', [3,4,5]] foo(); // []
babelコマンドでトランスパイルされたコードではArrayを生成してargumentsの内容をコピーしています。argumentsは配列に似ていますが実際はObjectのため、Arrayの持つ関数(forEachなど)を持っていないためです。
'use strict'; function foo() { for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } console.log(args); } foo(1, '2', [3, 4, 5]); // [1, '2', [3,4,5]] foo(); // []
Rest Paramterは引数の最後のみにしか指定できないという制約があります。下のような例ではbabelコマンドでトランスパイル時にエラーです。
function foo(...args, name="bar") { console.log(args); }
SyntaxError: rest.es6: Unexpected token (1:20) > 1 | function foo(...args, name="bar") { | ^ 2 | console.log(args); 3 | } 4 |
Spread Operator
Spread Operatorは配列を展開することができます。下の例で1つ目の関数fooの呼び出しでは配列を2つ渡しているので、Rest Paramterで受け取った関数では多次元配列となります。一方、2つ目の呼び出しでは"..."を使った構文を使い、Spread Operatorを適用すると配列が展開され1次元配列となります。
var x = [1,2,3]; var y = ['a','b']; var z = [7,8,...x,9]; function foo(...args) { console.log(args); } foo(z,y); // [[7, 8, 1, 2, 3, 9], ["a", "b"]] foo(...z,...y); // [7, 8, 1, 2, 3, 9, "a", "b"]
'use strict'; function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; return arr2; } else { return Array.from(arr); } } var x = [1, 2, 3]; var y = ['a', 'b']; var z = [7, 8].concat(x, [9]); function foo() { for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } console.log(args); } foo(z, y); // [7, 8, 1, 2, 3, 9, ["a", "b"]] foo.apply(undefined, _toConsumableArray(z).concat(y)); // [7, 8, 1, 2, 3, 9, "a", "b"]
CoffeeScriptやTypeScriptなどに代表されるaltJSではJavaScriptの言語仕様で扱いにくい点などを解決するツールとして広く使われています。同様にES6にもaltJSで実装されていたものと同種の改善が仕様に多く取り入れられています(現在のBabelなどのトランスパイラもES6の開発もaltJSの一つと言えるかもしれません)。
では、ES6がブラウザで対応された後、altJSは不要なものとなるでしょうか? 答えはNoだと考えられます。
例えば、TypeScriptには静的型付けなどES6にはない多くの機能を備えており、機能の多さではアドバンテージがあります。また、それらの機能はECMAScript標準として提案も行われており、今後ECMAScriptに取り込まれる可能性もあります。また、MV*フレームワークとして高い人気のあるAngularJSではバージョン2からTypeScriptが採用されるなど採用事例も増えています。
このように、今後もaltJSはECMAScript標準を補完する形で多くの場面で引き続き広く使われるでしょう。
最後に
本稿ではほんの一部ですがES6の機能についてBabelを使った例で紹介しました。Babeを利用することでES6の多くの機能を活用した開発が今からでも始められることが実感できたと思います。次回は今回紹介できなかった他のES6の機能とより実践的なBabelの使い方についての記事を掲載する予定です。
LINE株式会社ではJavaScriptエンジニアを募集しています。私たちと一緒にプラットフォーム・グローバル展開を発展させていきたい方はぜひご応募ください。