JavaScript(ES2015/ES6)予習会


# 概要

## 勉強会資料 ver0.01

2015/10/16(金) 19:30 - 20:30
JavaScript(ES2015/ES6)予習会
http://fukuoka-cam-study.connpass.com/event/21220/

## 参考資料

### ざっくり概要
 
*  ECMAScript 2015(ES6)の概要と次世代JavaScriptの新たな機能
https://html5experts.jp/1000ch/16984/  

* ECMAScript 6 — New Features: Overview & Comparison
http://es6-features.org/#Constants

### 予習のコーディングで使うサービス

* Runstant Lite
http://lite.runstant.com/about


#  アロー関数 Arrow Functions

http://goo.gl/HVfDbT

```javascript
var getEl = function(elementId){
  return document.getElementById(elementId);
};
window.onload = function() {
  var el1 = getEl("main-el-1");
  el1.textContent = "This is main-el-1";
};
```

↓functionをアロー関数に↓

http://goo.gl/bD0gCH

```javascript
var getEl = (elementId)=> document.getElementById(elementId);

window.onload = () =>{
  var el1 = getEl("main-el-1");
  el1.textContent = "This is main-el-1";
};
```

http://goo.gl/Yr6HAu

```javascript
var getEl = (elementId)=> document.getElementById(elementId);

window.onload = () =>{
  var ids = ["main-el-1","main-el-2"];
  ids.forEach(function(id){
    getEl(id).textContent = "This is " + id;
  });
};
```

↓forEachのfunctionをアロー関数に↓

http://goo.gl/YRCjUj

```javascript
  ids.forEach(id=>getEl(id).textContent = "This is " + id);
```

#  テンプレート Template Strings

http://goo.gl/HqbbXr

```javascript
window.onload = () =>{
  var ids = ["main-el-1","main-el-2"];
  ids.map(id=>getEl(id).textContent = "This is " + id);
};
```

↓文字列連結をテンプレートに↓

http://goo.gl/EbkMXc

```javascript
  ids.map(id=>getEl(id).textContent = `This is ${id}`);
```

# クラス Classes

## クラス定義 Class Definition

http://goo.gl/kzbBdO

```javascript
var getEl = (elementId)=> document.getElementById(elementId);

window.onload = () =>{
  var ids = ["main-el-1","main-el-2"];
  ids
    .map(id=>new UiLabel(id, `This is ${id}!`))
    .map(label=>label.render());
};

var  UiLabel = function(id, text){
  this.id = id;
  this.text = text;
};

UiLabel.prototype.render = function(){
  getEl(this.id).textContent = this.text;
};
```

↓prototypeをclassを使った書き方に↓

http://goo.gl/N9pr7T

```javascript
class UiLabel {
  constructor(id,text){
    this.id = id;
    this.text = text;
  }
  render(){
    getEl(this.id).textContent = this.text;
  }
} 
```

## 継承 Class Inheritance

http://goo.gl/jonCIL

```javascript
// Base Class
var UiBase = function(id){
  this.id = id;  
};

UiBase.prototype.getEl = function(elementId){
  return document.getElementById(elementId);
};

// Sub Class
var UiLabel = function(id, text){
  UiBase.call(this, id);
  this.text = text;
};

UiLabel.prototype = Object.create(UiBase.prototype);
UiLabel.prototype.constructor = UiLabel;

UiLabel.prototype.render = function(){
  this.getEl(this.id).textContent = this.text;
};
```

↓callやObject.createからextendsへ↓

http://goo.gl/ngLXlU

```javascript
// Base Class
class UiBase {
  constructor(id){
    this.id = id;
  }

  getEl (elementId){
    return document.getElementById(elementId);
  }
}

// Sub Class
class UiLabel extends UiBase {
  constructor(id, text){
    super(id);
    this.text = text;
  }

  render(){
    this.getEl(this.id).textContent = this.text;
  }
}
```

## スタティックメソッド Classes Static Members

http://goo.gl/yCPd2z

```javascript
window.onload = () =>{
  var ids = ["main-el-1","main-el-2"];
  ids
    .map(id=>UiUtil.create(id))
    .map(label=>label.render());
};

var UiUtil = function() {};
UiUtil.create = function(id){
  return new UiTextBox(id,`This is ${id}!`);
};
```

↓staticを使って書き換え↓

http://goo.gl/CshsCL

```javascript
window.onload = () =>{
  var ids = ["main-el-1","main-el-2"];
  ids
    .map(id=>UiUtil.create(id))
    .map(label=>label.render());
};

class UiUtil {
  static create(id){
    return new UiTextBox(id,`This is ${id}!`);
  }
}
```

# 分割代入 Destructuring Assignment


http://goo.gl/92lDOQ

```javascript
window.onload = () =>{
// ...省略...
  ids
    .map(obj=>UiUtil.create(obj.id, obj.type))
    .map(label=>label.render());
};

class UiUtil {
  static create(id, type){
    if (type === UiUtil.TYPE.LABEL){
      return new UiLabel(id,`This is ${id}!`);
    }
    return new UiTextBox(id,`This is ${id}!`);
  }
// ...省略...
}
```

↓関数引数での分割代入↓

http://goo.gl/59Ev1I

```javascript
window.onload = () =>{
// ...省略...
  ids
    .map(obj=>UiUtil.create(obj))
    .map(label=>label.render());
};

class UiUtil {
  static create({id, type}){
    if (type === UiUtil.TYPE.LABEL){
      return new UiLabel(id,`This is ${id}!`);
    }
    return new UiTextBox(id,`This is ${id}!`);
  }  
// ...省略...
}
```

# 関数パラメータの拡張

## デフォルトパラメータ

http://goo.gl/51id2U

```javascript
window.onload = () =>{
  var ids = [
    {id: "main-el-1"},
    {id: "main-el-2", type: UiUtil.TYPE.INPUT}
  ];
  
  ids
    .map(obj=>UiUtil.create(obj.id, obj.type))
    .map(label=>label.render());
};

class UiUtil {
  static create(id, type){
    type = (type===undefined)? UiUtil.TYPE.LABEL: type;
    if (type === UiUtil.TYPE.LABEL){
      return new UiLabel(id,`This is ${id}!`);
    }
    if (type === UiUtil.TYPE.INPUT){
      return new UiTextBox(id,`This is ${id}!`);
    }
    throw new Error("No UI!");
  }
// ...省略...
}
```

↓typeのデフォルトパラメータでLABEL設定↓

http://goo.gl/aLQq7H

```javascript
class UiUtil {
  static create(id, type = UiUtil.TYPE.LABEL ){
    if (type === UiUtil.TYPE.LABEL){
      return new UiLabel(id,`This is ${id}!`);
    }
    if (type === UiUtil.TYPE.INPUT){
      return new UiTextBox(id,`This is ${id}!`);
    }
    throw new Error("No UI!");
  }
  
// ...省略...
}
```

# アロー関数 Arrow Functions

## thisの動きが違います

http://goo.gl/2w2LVi

```javascript
class UiTextBox extends UiBase {
// ...省略...
  setEvents(){
    var _this = this;
    this.el.addEventListener("change",function(){
      _this.handlers.forEach(
        (handler)=>handler(_this.el.value)
      )
    });
  }
// ...省略...
}
```

↓functionをアロー関数に↓

http://goo.gl/Q22vwt

```javascript
  setEvents(){
    this.el.addEventListener("change", ()=>
      this.handlers.forEach((handler)=>handler(this.el.value))
    );
  }
```

# ブロックスコープ

## let

http://goo.gl/7jjuV2

```javascript
class UiLabel extends UiBase {
  constructor(id, model){
    super(id, model);
  }
  
  render(){
    this.getEl(this.id).innerHTML = null;
    for (var i=0; i<3; i++){
      var span = document.createElement("span");
      span.textContent = ` ${i}:${this.model.text} `;
      setTimeout(
        ()=>this.getEl(this.id).appendChild(span)
      , 1000*i);
    }
  }
}
```

↓varをletに変えると動作が変わります↓

http://goo.gl/0H3SpZ

```javascript
class UiLabel extends UiBase {
  constructor(id, model){
    super(id, model);
  }
  
  render(){
    this.getEl(this.id).innerHTML = null;
    for (let i=0; i<3; i++){
      let span = document.createElement("span");
      span.textContent = ` ${i}:${this.model.text} `;
      setTimeout(
        ()=>this.getEl(this.id).appendChild(span)
      , 1000*i);
    }
  }
}
```

# クラス Classes 

## Getter/Setter が使えます

http://goo.gl/0H3SpZ

```javascript
class Model {
  constructor(text){
    this.text = text;
  }
}
```

↓値を設定するときに処理を挟めます↓

http://goo.gl/HgpZpV

```javascript
class Model {
  constructor(text){
    this.version = 1;
    this._preText = "";
    this._text = text;
  }
  
  set text(text){
    if ( this._text === text ){
      return;
    }
    this.version++;
    this._preText = this._text;
    this._text = text;
    console.log(`ver ${this.version} pre: ${this._preText}`);
  }
  
  get text(){
    return this._text;
  }
}
```

# 関数パラメータの拡張

## Rest Parameter

http://goo.gl/IJHM8b

```javascript
window.onload = () =>{
  var model = new Model("hello");
  UiUtil.createEls(
    model,
    {id: "main-el-1"},
    {id: "main-el-2", type: UiUtil.TYPE.INPUT},
    {id: "main-el-3"}
    // ...増やしたいだけ増やす...
  );
};

class UiUtil {
  static createEls(model){
    var handlers = [];
    var ids = Array.prototype.slice.call(arguments, 1);

    var els = ids.map(obj=>UiUtil.create(obj.id, obj.type, model))
                 .map((el)=>el.setHandlers(handlers));
  
    var handler = (value)=> {
      model.text = value;
      els.forEach((el)=>el.render());
    };
    
    handler(model.text);
    handlers.push(handler);
  }
// ...省略...
}
```

> https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/slice
> slice メソッドは 「配列の様なオブジェクト」も変換する事が可能です。配列の様なオブジェクトの一例として、arguments（関数が受け取った引数）が挙げられます。


↓argumentsを変換してとっていたのが ...でとれる↓

http://goo.gl/ShSFFL

```javascript
  static createEls(model, ...ids){
    var handlers = [];

    var els = ids.map(obj=>UiUtil.create(obj.id, obj.type, model))
                 .map((el)=>el.setHandlers(handlers));
  
// ...省略...
  }

```

# Generator Functions

http://goo.gl/s15KLP

```javascript
var f = function(){
  var cnt = 0;
  return function(){
    cnt++;
    if (cnt===1){
      return "aaa";
    }
    if (cnt===2){
      return "bbb";
    }
  };
}();
window.onload = function() {
  console.log(f());
  console.log(f());
}
```

↓yieldで書くと↓

http://goo.gl/CP7VtI

```javascript
var f = function *(){
  yield "aaa";
  yield "bbb";
};
window.onload = function() {
  var gene = f();
  console.log(gene.next().value);
  console.log(gene.next().value);
}


```


# TODO


* [ ] promise
  http://azu.github.io/promises-book/
  https://github.com/bevacqua/promisees
  
* [ ] Symbol
* [ ] Reflect
* [ ] Proxy
* [ ] Set/WeakSet
* [ ] Map/WeakMap
* [ ] Module
* [ ] Iterator & For-Of Operator

* [ ] 時間があれば...会社の...求人の...宣伝.... http://www.cam-net.co.jp/