この記事はアクトインディ Advent Calendar 2016 3日目になります。 どうぞよろしくお願いします。
ES2015の新記法について、まとめました。
ES2015の新記法
変数の宣言
let
- 変数の重複を許可しない
- ブロックスコープ({})を認識する
var x = "foo";
var x = "bar";
let y = "foo";
let y = "bar";
if (true) {
var i = 5;
}
console.log(i);
if (true) {
let x = 5;
}
console.log(x);
定数(const)
const TAX = 1.08;
let price = 100 * TAX;
データ型
分類 | データ型 | 概要 | |
---|---|---|---|
基本型 | 数値型(number) | ||
基本型 | 文字列型(string) | シングル/ダブルクォートで囲まれた0個以上の文字の集合 | |
基本型 | 真偽型(boolean) | true(真)/false(偽) | |
基本型 | シンボル型(symbol) | シンボルを表す(ES2015の新記法) | |
基本型 | 特殊型(null/undefined) | 値が空、未定義であることを表す | |
参照型 | 配列(array) | データの集合(各要素にはインデックス番号でアクセス可能) | |
参照型 | オブジェクト(object) | データの集合(各要素には名前でアクセス可能) | |
参照型 | 関数 | 一連の処理(手続き)の集合 | ### String型の不思議 |
let x = new String("foo");
let y = "foo";
x == y
=>true
let z = new String("foo");
x == z
=>false
x, zが一致しないのはnew String
で生成したものは、object
になります。
参照型になっているからこの現象が起きます。
typeof(x);
=>"object"
x,yが比較して一致するのは、文字列リテラルを比較する場合は、一時的にString型にしているからです。
文字列リテラルを持つ値は、String オブジェクトのあらゆるメソッドを呼び出すことができます。JavaScript は自動的に文字列リテラルを一時的な String オブジェクトに変換し、メソッドを呼び出して、その後一時的に作られた String オブジェクトを破棄します。String.length プロパティを文字列リテラルで用いることもできます :
シンボル
- Rubyのシンボルと違い、symbolで生成されたものはユニーク扱いになる
let x = Symbol('sym');
let y = Symbol('sym');
typeof(x);
=>symbol
x.toString();
=>Symbol(x)
x == y
=>false
Mapオブジェクト
伝統的な書き方
var x = { 'apple': 'りんご',
'orange': 'みかん',
'strawberry': 'いちご' }
console.time('associative_array');
x.apple
console.timeEnd('associative_array');
map
var x = new Map([['apple', 'りんご'],
['orange', 'みかん'],
['strawberry', 'いちご']]);
x.set('banana', 'バナナ')
console.time('map');
x.get('apple');
console.timeEnd('map');
x.keys();
x.size
オブジェクトリテラルとの違い
- 任意の型でキーを設定できる
- オブジェクト/NaNでもキーになりうる
- マップのサイズを取得できる
- sizeメソッドで要素数を取得できる
- クリーンなマップを作成できる
- オブジェクトリテラルは、Objectそのもの 配下にはObjectが標準で用意しているプロパティが最初から存在している
キーに関わる3つの注意点
- キーは「===」演算子で比較される
- 特別なNaNは特別ではない
var x = new Map();
x.set(NaN, 'foo');
x.get(NaN);
- オブジェクトの比較には注意
var x = new Map();
x.set({}, "foo");
x.get({});
Setオブジェクト
- 重複しない値の集合を操作する(初めての概念自体)
let i = new Set([1, 5, 100, 10, 5]);
for (var int of i.values()) {
console.log(int);
}
- オブジェクトの比較はMapと同じ
書き方
代入
分割代入
- 端数は切り捨てられる
- オブジェクトの場合は、変数の並び順は考慮しなくても大丈夫
配列
let [x, y, z] = [1, 2];
連想配列(オブジェクト)
let associative_array = { x: 1,y: 2, z: 3 }
let { x, z, y } = associative_array;
関数
アロー関数
- 関数リテラルのfunctionを記入しなくて良い
- 1行で書く場合は、returnを書く必要がない
関数リテラル
let getSquare = function(num) {
return num * num;
}
アロー関数
let getSquare = (num) => {
retun num * num;
}
let getSquare = (num) => num * num;
変数展開
テンプレート文字列
let name = "Tom";
let greet = `Hello ${name}`;
引数
引数のデフォルト値
- 今までは引数にデフォルト値を渡すことはできなかった
function getSquare(num = 2) {
return num * num;
}
let getSquare = (num = 2) => num * num;
getSquare(5);
名前付き引数
- {}を使用することで名前付き引数になる
- 使用する場合に{}で指定する
let getSquare = ({num = 2}) => num * num;
getSquare({num: 5});
let getSquare = ({num}) => num * num;
getSquare({num: 5});
可変長引数の定義
...(スプレッド演算子)
で可変長引数になる
function sum(...nums) {
let result = 0;
for (let num of nums) {
result += num;
}
return result;
}
「…」演算子による引数の展開
- 「…」演算子は、実引数で利用することで、配列(正確にはfor..ofブロックで処理できる)をここの値に展開する
Math.max(1, 3, 5, 4);
let x = [1, 3, 5, 4]
Math.max(x);
=> NaN
Math.max(...x);
=> 5
引数の戻り値
複数の戻り値を個別の変数に代入する
function getMaxMin(...nums) {
return[Math.max(...nums), Math.min(...nums)];
}
nums = [1, 4, 100, 5, 904580259, 40]
let x = getMaxMin(...nums);
let [max, min] = getMaxMin(...nums);
クラス
定義方法
- constructorで初期値を定義する
class Member {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
getName() {
return this.firstName + this.lastName;
}
}
- 関数として呼び出すことは不可能
- 定義前のクラスは呼び出せない
let m = Member("foo", "bar");
class Member {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
getName() {
return this.firstName + this.lastName;
}
}
静的メソッド(特異メソッド)を定義する
- staticで定義する
class Member { constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
static greet() {
return "hello"
}
}
継承する
- extendsで継承
class Actindi extends Member {
static service() {
return "iko-yo";
}
}
基底クラスのメソッド/コンストラクターを呼び出す(super)
- superで基底クラスを継承 or 上書き
書き方
// construcor
super(args)
// method
super.method();
class Actindi extends Member {
constructor(firstName, lastName, post) {
super(firstName, lastName);
this.post = post;
}
getName() {
return this.post + super.getName();
}
}
モジュール
- exportでアクセスできるようにする
utility.js
export class Member {
...
}
export class Actindi {
...
}
- importで取り込む
import { Member, Actindi } from './utility'
let m = new Member("foo", "bar");
importの記法
- モジュール全体をまとめてインポート
- asでモジュールの別名を指定しておく
import * as app from './utility'
let m = new app.Member("foo", "bar");
- モジュール内の個々の要素に別名を付与する
import { Member as MyMember, Actindi as Act } from './utility'
let m = new MyMember("foo", "bar");
メソッド編
配列
for..of(配列を取り出す)
過去
let nums = [1, 2, 3];
for(var i = 0, len = nums.length; i < len; i++){
console.log(nums[i]);
}
現在
let nums = [1, 2, 3];
for (num of nums) {
console.log(num);
}
オブジェクト
assign
- 同名のプロパティは後のもので上書きされる
let x = { name: "foo",
email: "foo@foo.com",
login: "var" }
let y = { name: "bar" }
let z = { title: "baz" }
Object.assign(x, y, z)
x
=>Object {name: "bar", email: "foo@foo.com", login: "var", title: "baz"}
処理
Strictモード
- 「仕様として存在するが、安全性や効率面で利用すべきでない構文」を通知する
分類 | Strictモードによる制限型 |
---|---|
変数 | var命令の省略禁止 |
変数 | 将来的に追加予定のキーワードを予約語に追加 |
変数 | 引数/プロパティ名の重複を禁止 |
変数 | undefined/nullへの代入を禁止 |
命令 | with命令の利用禁止 |
命令 | arguments.calleeプロパティへのアクセスを禁止 |
命令 | eval命令で宣言された変数を、周囲のスコープに拡散しない |
その他 | 関数配下のthisはグローバルオブジェクトを参照しない(undefinedとなる) |
その他 | 「0〜」の8進数表記は禁止 |