2016年7月24日 星期日

ECMAScript 6: Class, Extends And Symbol.Species

ES6 新增了 Class 類別的用法,甚至可以簡單繼承,以下筆記。

Class

一個簡單的 Class 與調用,宣告如下
class test{
    constructor(x,y){ //建構子。  白話:被 new 出來後給予的參數。
        this.x = x;
        this.y = y;
    } //不用加上 , 逗號

    getX(){
        return this.x;
    }

    getY(){
       return this.y;
    }    
}

//調用
var t = new test(5,10);
t.getX(); //5
t.getY(); //10

Extends

在有 Class, Extends 之前,可以先來看一下 apply, call 來做繼承:
function setValue(a,b){
    this.a = a; //僅設定 this 的 a
    this.b = b; //僅設定 this 的 b
}

function feature(a,b,c){
    this.c = c;

    setValue.call(this, a, b);
    //or setValue.apply(this,[a,b]);

    this.getSum = function(){
        return this.a + this.b + this.c;
    }
}

var f = new feature(10,15,20);
console.log(f.getSum());



//bind 綁物件的做法:
var obj = {
    c : 200
}

function test(a,b){
    this.a = a;
    this.b = b;
    this.c = this.c || 'No Set'; //Bug: (`0 == false`) is `true` ,so number is 0 will let this.c = 'No Set' , so c should be string.

    console.log(this.a);   
    console.log(this.b);
    console.log(this.c);
}

var test1 = test.bind(obj,10,20);
test1(); //10  20  200


ES6 的 Extends 主要是繼承上一個 Class 的內容,複製過來 (包含 this 值)。
class test{
    constructor(x,y){ //建構子。  白話:被 new 出來後給予的參數。
        this.x = x;
        this.y = y;
    } //不用加上 , 逗號

    getX(){
        return this.x;
    }

    getY(){
       return this.y;
    }    
}

class advanced extends test{ //一個繼承的用法
    constructor(x,y,z){
        super(x,y); //super() 可以調用父 Class 的建構子 (constructor),這麼做是因為 this 的功能共用。
        this.z = z;

        //super.[function name] 可以呼叫父 Class 的原有方法。
        console.log(super.getX() + super.getY()); 
    }

    getZ(){
        return this.z;
    }
}

//調用
var t = new advanced(5,10,15);
t.getX(); //5 (是 super 的)
t.getY(); //10 (是 super 的)
t.getY(); //15 (是自己的)

知道這個"方法"是怎麼 New 出來的

從以下範例可以看到其用法:
class test{
    constructor(){
        console.log(new.target); //如果是 undefined 代表不是用 new 呼叫的
        console.log(new.target.name); //顯示調用的方法,這裡是 `test`
    }
}

class advanced extends test{
    constructor(){
        super(); //原本 test 的 `new.target.name` 會變成 `advanced`
        console.log(new.target.name); //這裡是 `advanced`
    }

    show(){
        console.log(new.target); //如果不是 new 呼叫,會變成 undefined
    }
}

//調用
var test1 = new test();//xxx, test

var test2 = new advanced(); //xxx, advanced, advanced

test2.show(); //undefined, 因為不是用 new 呼叫的


Static 靜態方法

靜態方法,不需要 new 就可以直接調用。
class test{
    
    constructor(){
        this.a = 10;
    }
    
    
    static doSomething(){
        console.log("something");
        console.log(this.a); //undefined  沒經過初始化
    }
}

//調用
test.doSomething();// something undefined

Symbol.species

Symbol.species 可以在執行你的 Class 後,回傳指定的物件或類型,而不是你的物件。

觀望以下:
class test{
    static get[Symbol.species](){
        return this; //沒有父物件,把自己丟回去 (不管是取用什麼值,都會丟出這個 static get[Symbol.species] 方法 return 的東西)
    }
}

class advanced extends test{
    static get[Symbol.species](){
        return test; //丟 test, 這樣所有用 advanced 類別的人,收到的只會是 test 類型,換之丟 Array, 就會有 Array 的類型。
    }

    getAdvanced(){
        return new this.constructor[Symbol.species](); //因為 var a = new advanced(); 的 a 只有一次,所以如果其他變數想要得到 a 的 "實體" (不想在 new) ,而且又是新的 "實體",可以用這個寫法。
    }
}


var a = new test();
var b = new advanced();

a instanceof test
//true
b instanceof test
//true
b instanceof advanced
//true
a instanceof advanced
//false

Reference:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/species

沒有留言:

張貼留言

© Mac Taylor, 歡迎自由轉貼。
Background Email Pattern by Toby Elliott
Since 2014