Posted at

ES6を少しだけモミモミしてみる

More than 3 years have passed since last update.


はじめに

先日勉強会に参加したところES6の話題が多かった印象を受けたので、勉強会で出てきた言葉を元に少し調べました。

js自体がまだちゃんと書けていない私としては、ES6を学ぶのはしんどいですが、いつか輝く為に少しずつ学ぼうと思います。


Template literal

Template literalを使うと、文字列の連結をスッキリかけるようになります。

+join()を使わなくてもいいのです!

やり方は、${}`(バッククオート)を利用して文字列の連結を行います。


バッククオート内の${}の中が評価され、その結果が置き換わります。


ES5

var str1 = 'スーパー';

var str2 = '合体';

var str = 'Template literalで文字列の' + str1 + 'の' + str2 + '!';

console.log(str);//Template literalで文字列のスーパーの合体!


ES6

var str1 = 'スーパー';

var str2 = '合体';

var str = `Template literalで文字列の${str1}の${str2}!`;

console.log(str); //Template literalで文字列のスーパーの合体!


式を評価して表示

${}の中には変数だけでなく式をいれることができます。


ES5

var str = 5 * 5 + "は" + (5 + 5 + 5 + 5 + 5) + "!";


ES6

var str = `${5*5}は${5+5+5+5+5}!`;


Default parameters

JavaScriptでの、関数の引数は、undefinedが初期値となります。


ES5では、引数の初期値を自由に設定することができなかった為、関数内で引数をチェックして、

undefinedなら初期値を設定するようなことをやってました。

ES6からは、下記例のように引数の初期値を設定できます。


ES5

function defaultParameters(a) {

var b = arguments.length <= 1 || arguments[1] === undefined ? 'あるとうれしい!' : arguments[1];

return a + b;
}

var str = defaultParameters('初期値が');
console.log(str); //初期値があるとうれしい!


ES6

function defaultParameters(a, b = 'あるとうれしい!') {

return a + b;
}

var str = defaultParameters('初期値が');
console.log(str);//初期値があるとうれしい!


Rest parameters

今まで引数が可変の(いくつ渡ってくるかわからない)場合、argumentsを使用してやりくりしていましたが、Rest parametersを使用すれば、引数を可変長で受け取ることができます。


ES5

function rest() {

for (var _len = arguments.length, values = Array(_len), _key = 0; _key < _len; _key++) {
values[_key] = arguments[_key];
}

console.log(values);
}

rest(1, 2, 3);//[1,2,3]


ES6

function rest(...values) {

console.log(values);
}

rest(1,2,3);//[1,2,3]

Rest Parametersのルールとして、引数の最後で渡す必要があります。

下記の場合、可変長引数の...valuesが第1引数として設定されている為、エラーとなります。

function rest(...values,value) {

console.log(values);
}

下記ばOK。

function rest(value,...values) {

console.log(values);
}


Spread operator

Spread operatorを使うと配列同士を結合したりする場合に便利です。


ES5

var arr1 = [0, 1, 2];

var arr2 = [3, 4, 5];
var arr3 = [].concat(arr1, arr2);

arr1.push.apply(arr1, arr2);

console.log(arr1); // [0, 1, 2, 3, 4, 5]
console.log(arr3); // [0, 1, 2, 3, 4, 5]


ES6

var arr1 = [0, 1, 2];

var arr2 = [3, 4, 5];
var arr3 = [...arr1,...arr2];

arr1.push(...arr2);

console.log(arr1); // [0, 1, 2, 3, 4, 5]
console.log(arr3); // [0, 1, 2, 3, 4, 5]


Destructuring

Destructuringは分割代入という、新しい変数代入の方法です。


配列で受け取る

var [a,b] = [1,2];

console.log(a,b)//1 2

var [a, b, ...rest] = [1, 2, 3, 4, 5];
console.log(a,b,rest)//1 2 [3,4,5]


関数の戻り値で受け取る

var [a,b] = (function(){return [1,2];})();

console.log(a,b)//1 2


一部省略や、デフォルト値を設定する

var [a,,[b,c],d=5] = [1,2,[3,4],5];

console.log(a,b,c,d);//1,3,4,5


オブジェクトで受け取る

var obj = {name:'太郎',sex:'男',age:30};

//必要なプロパティだけ代入
var {name:n,age:a} = obj;

console.log(n,a)//太郎 30

上記をES5で書くとこんな感じ。こっちのほうがわかりやすいような気がするのは、私が未熟なせいでしょう。。。


ES5

var obj = { name: '太郎', sex: '男', age: 30 };

var n = obj.name;
var a = obj.age;

console.log(n, a); //太郎 30


Blockscope


let

letを使うことで、関数スコープでなく、ブロックスコープを使用することができます。


letを使った場合

if(true){

let a = 1;
console.log(a);//1
}

console.log(a);//error


varを使った場合

if(true){

var a = 1;
console.log(a);//1
}

console.log(a);//1

ES5の場合は即時関数を利用してスコープをつくってました。

var a = 0;

(function(){
var a = 1;
console.log(a);//1
})();
console.log(a);//0

ES6はletを使うことでスコープの範囲がわかりやすくなりました。

var a = 0;

{
let a =1;
console.log(a);//1
}
console.log(a);//0


関数宣言をブロックスコープ内に定義

関数宣言もブロックスコープ内に定義することができます。

{

function block(){return 1;}
console.log(block());//1
{
function block(){return 0;}
console.log(block());//0
}
console.log(block());//1
}


const

定数を定義することができます。

const a = 1;

console.log(a);//1

//再定義はエラーとなる
const a = 1;//error

//代入は無視される
a = 0;
console.log(a);//1


Arrow Function

アロー関数を使用することで、関数の定義が短くかける。


ES5

[1, 2, 3].map(function (v) {

console.log(v);
});


ES6

//引数が一つの時には「(v)の()」を省略できる

[1,2,3].map(v=>{console.log(v);});

//下記でもOK
//[1,2,3].map((v)=>{console.log(v);});


Arrow Functionのthis

アロー関数のthisは、関数が実行されれたときに決まるのではなく、関数が定義されたときに決まる。

アロー関数を使うことで、selfとか_thisとかを使わないくて済むようになる。

function Myfunc(){  

this.name = '太郎';
setTimeout(()=>{
console.log(this.name);//太郎
})
}

new Myfunc();

従来のfunctionで定義した場合

function Myfunc(){

this.name = '太郎';

setTimeout(function(){
//thisはwindowを参照する
console.log(this.name);//undefined
},100)
}

new Myfunc();


Async関数(ES7)

async、awaitを使うと非同期処理を、まるで同期処理を書いているように書けます。

下記の例のように、awaitを追加した関数は、その処理が終わるまで次の処理に移りません。


awaitを使う場合は、awaitを使う関数をasync functionをにする必要があります。

※このあたりまだちゃんと理解できていない為、記載の表現に誤りがあるかも。。。

function asyncGet(req, wait){ 

return new Promise(
resolve => setTimeout(function(){resolve(req)}, wait)
);
}

async function test(){
console.log(await asyncGet("リクエスト1", 1000));
console.log(await asyncGet("リクエスト2", 100));
console.log(await asyncGet("リクエスト3", 3000));
console.log(await asyncGet("リクエスト4", 200));

//リクエスト1
//リクエスト2
//リクエスト3
//リクエスト4
};

test();

いままでは下記のように書いてました。

上記にくらべると冗長な感じがしますし、

async、awaitを使ったほうがコードの見通し良くなった気がします。

function asyncGet(wait){ 

return new Promise(
resolve => setTimeout(function(){resolve()}, wait)
);
}

function test(){
asyncGet(1000)
.then(function(){
console.log("リクエスト1");
return asyncGet(1000);
})
.then(function(){
console.log("リクエスト2");
return asyncGet(100);
})
.then(function(){
console.log("リクエスト3");
return asyncGet(3000);
})
.then(function(){
console.log("リクエスト4");
return asyncGet(200);
});
};

test();


終わり

ES6からはClassも使えるようになり、色々やれることが増えるようです。

記載の内容以外にも沢山便利な機能があるようなので、今後も調べていこうと思います。