ECMAScriptとは
- ECMAScriptはJavaScriptの中核仕様を抜き出して標準化したもの
- 開発当初のJavascriptは、ブラウザによる独自の拡張が多く、互換性が低かったため、Ecma Internationalが中心となりECMAScriptが開発された
ES2015 (ES6)とは
先日策定された、ECMASCriptの6th Editionのことであり、当初はES6と呼ばれているが、正式名称をECMASCript2015(ES2015と呼ばれる)とし、今後は年単位のリリースを予定しているとのこと
[公式サイト]http://www.ecma-international.org/ecma-262/6.0/index.html
ES2015で可能となる新たなシンタックス
-
let
・const
キーワードによる変数宣言 -
class
構文 - 関数の引数のデフォルトパラメータ(Default Parameters)
- アロー関数(Arrow Functions)
- 分割代入(Destructing Assignment)
- 配列展開(Array Spread)
- 関数の可変長引数(Rest Parameters)
- 関数のデフォルト引数
- テンプレート文字列(Template Strings)
- importとexportによるモジュール構文(Module)
let constによる変数宣言
ES5までは関数スコープのみしか存在しなかったため、var
による変数宣言に対して、スコープを利用するためには、無名関数を用いてスコープの作成をしていたが、
ES2015ではブラケット{}
によるブロックスコープが可能となり、ブラケット内でlet
やconst
により定義された変数はそのブラケットのスコープ内のみで生きることができる。
const
は定数を宣言したい時に用いられ、const
で宣言された変数は、宣言時を除いて値の代入が不可能である。再代入を行おうとすると、例外が発生し、プログラムがストップするため、プログラムレベルで値の不変性が保証される。
let foo = [1, 2, 3];
{
let foo = [4, 5, 6];
console.log(foo);
// => 4, 5, 6
}
console.log(foo);
// => 1, 2, 3
{
const PI = 3.14;
const circleArea = function (radius) {
return radius * radius * PI;
};
console.log(circleArea(3));
// => 28.26
// ここでPI = 3.1415;のような再代入を行おうとすると、例外が発生する
}
console.log(PI);
// => undefined
クラス構文
ES5までではprototype(あるオブジェクトの元になるオブジェクトという概念。RubyやJavaなどのクラスベースオブジェクト指向に対し、javascriptはプロトタイプベースオブジェクト指向と呼ばれる。)を利用することで、クラスのようなものを作成してきた。
function Human(name) {
this.name = name;
}
Human.prototype.hello = function () {
console.log('My name is ' + this.name);
};
Humanオブジェクトはhelloオブジェクトをprototypeとしてできており、Humanオブジェクトはhelloオブジェクトに対する暗黙の参照をもっているため、helloというプロパティでhelloオブジェクトを呼び出すことができる
obj = new Human('Izmeal')
obj.hello
//=> 'My name is Izmeal'
これを、class構文を用いると、
class Human {
constructor(name) {
this.name = name;
}
hello() {
console.log('My name is ' + this.name);
}
}
obj = new Human('Koyabu')
obj.hello
//=> 'My name is Koyabu'
class構文についてもう少しみてみる。
constructorメソッド
constructorメソッドは、クラスがnewされた時に実行されるメソッドであり、クラス内で共通して使われるプロパティの初期値の定義などを行う。1つのクラスに1つしか定義できない。先ほどの例ではnameの初期値を代入している。(Rubyでいうinitializeメソッド)
prototypeメソッド
先ほどのHumanクラスのhelloのように、クラスのインスタンスから呼び出せるメソッドをprototypeメソッドという。(Rubyでいうインスタンスメソッド)
staticメソッド
インスタンスを生成する必要なくクラス名.メソッド名
の形で呼び出せるメソッド。(Rubyでいうクラスメソッド)
class Human {
constructor(name) {
this.name = name;
}
hello() {
console.log('My name is ' + this.name);
}
static num_of_hands() {
console.log(2)
}
}
Human.num_of_hands()
//=> 2
クラスの継承
extends キーワードをクラス宣言、もしくはクラス式内に記述することで、他のクラスの子クラスを定義できる。
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(this.name + ' makes a noise.');
}
}
class Dog extends Animal {
speak() {
console.log(this.name + ' barks.');
}
}
子クラス内で、親クラスのconstructorはsuper()
で呼び出せ、親クラスのメソッドは、super.メソッド名()
で呼び出せる。
アロー関数による関数宣言
従来のfunciton
を使った関数宣言に加えて、=>
を用いた関数宣言が可能
アロー関数による関数宣言の特徴としては、
* 常に匿名関数
* 引数が一つの場合は()が省略可能
* bodyが単一式の場合は、{}やreturnを省略できる
// 従来のfunctionを使った書き方
var plus = function(x, y) {
return x + y;
};
// アロー関数
let plus = (x, y) => {
return x + y;
};
// 単一式の場合はブラケットやreturnを省略できる
let plus = (x, y) => x + y;
this
は関数が定義されたスコープにおけるthis
を引き継ぐ
これに対し、functionによる関数定義では、それぞれの関数がそれ自身の thisの値を新たに定義していた。(コンストラクターでは新しいオブジェクト、 strict モードでの関数呼び出し時はundefined、関数が"オブジェクトのメソッド" として呼び出された場合はそのオブジェクト、など)リテラルを返す場合には()で囲む必要がある。(そうでないと波括弧の中は文としてパーシングされてしまう。)
var func = () => ({ foo: 1 });)
アロー関数はSafariは未対応なので要注意
分割代入
一度に複数の変数に、複数の値を代入できる。
var name = Izmeal;
var age = 21;
を
var [name, age] = ['Koyabu', 20];
とできる
配列展開
関数の呼び出し、配列への代入、構造化代入に対して、...
により、配列を展開して用いる事ができる
var array = [1, 2, 3]
function f(x, y, z) { }
f(...array);
//f(1, 2, 3)という引数での関数fの呼び出しと同義
[...array, 4, 5, 6]
//[1, 2, 3, 4, 5, 6]となる
var x
var y
var z
var variables = [x, y, z]
[a, b, ...variables] = [1, 2, 3, 4, 5];
// a = 1, b = 2, x = 3, y = 4, z = 5とした場合と同じ
可変長引数
function f(x, ...ys) {
console.log(x, ys);
}
f(2, 3, 5);
//=> 2 [ 3, 5 ]
デフォルト引数
function multiply(a, b = 1) {
return a*b;
}
multiply(5); // 5
のように引数の()括弧内で代入を行うことで、デフォルト値を設定できる
テンプレート文字列
``で文字列を囲むことで、文字列内での変数展開が${}で行え、改行もそのまま反映できる
var name = 'Koyabu'
var hello = `My name is
${name}`
console.log(hello)
//=>My name is
//Koyabu