1. 程式人生 > >ES6中的Class

ES6中的Class

用法 proto 提升 調用方法 調用 () 自動 添加 rop

prototype

class語法中 prototype 依然存在, 類的所有方法都定義在了類的 prototype 屬性上。

class Demo {
    constructor() {
        //
    }

    toString() {}

    toValue() {}
}
// 等同於

Demo.prototype = {
    constructor: Demo,
    toString() {},
    toValue() {}
}

註意在類的方法之間不要加 , 號, 否則報語法錯誤,在類的實例上調用方法還是調用原型上的方法。

在類內部定義的方法都是不可枚舉的, 這點應該引起註意;

class Demo {
    constructor() {
        //
    }

    toString() {}

    toValue() {}
}
Object.keys(Demo.prototype)     // []
Object.getOwnPropertyNames(Demo.prototype)  // ['constructor', 'toString', 'toValue']

類名的屬性可以采用動態屬性:

class Demo {
    constructor() {}
    [someProp]() {}
}

註意上面的例子中的 [] 不可替換成 (), 否則報語法錯誤;

constructor方法

constructor 方法是類的默認方法,通過 new 命令生成對象實例時自動調用該方法。一個類必須要有 constructor 方法, 未顯示定義, js會默認添加一個 constructor
, 該方法默認返回實例對象(this),這點與 es5 的構造器表現一樣, 也可以指定返回別的對象, 但是指定返回 基本類型 的值會阻止不了返回 this;

實例對象

生成實例的方法與 es5 的寫法一致, 要使用 new, 如果沒有 new 調用 class 會報錯
類的所有實例共享一個原型對象

let
demo1 = new Demo(); let demo2 = new Demo(); demo1.__proto__ === demo2.__proto__ // true

name屬性

本質上 class 只是 es5 的構造函數的一層包裝, 很多函數具備的特性它也有, name 屬性也不例外;

class表達式

const Demo = class some {
    getClassName() {
        return some.name;
    }
}

let demo = new Demo();
demo.getClassName()     // some
some.name               // 報錯

跟在表達式後面的名字(如some),只能在類的作用域能引用, 其他位置引用不到, 盡管在全局環境下定義也拿不到, 這樣做的一個應用場景是替代 arguments.callee, 因為在嚴格模式下
arguments.callee 是不能被使用的, es6 已經把整個語言升級到了嚴格模式,我們可以用表達式右邊的 name 來取代 arguments.callee; 這個地方和 es5 完全一致;

不存在變量提升

new Demo();     // 報引用錯誤;
class Demo() {};

嚴格模式

類和模塊內部默認已經是嚴格模式;

class繼承

** 基本用法 **
通過 extends 實現繼承, 這點比 es5 實現繼承要清晰和方便;

class Demo extends Array {}

類的內部用 super 代指父類, 子類沒有自己的 this 對象, 而是繼承了父類的 this 對象, 然後對其加工, 如果不調用 super, 子類就拿不到 this 對象

** 原生構造函數的繼承 **

由於 class 是先拿到父級的 this, 這點和 es5 不一樣, 子類能拿到原生構造器內部的屬性, 所以能夠完整繼承原生構造器

class Demo extends Array {
    constructor(...args) {
        super(...args);
    }
    push(num) {
        super.push(num);
        return this;
    }
}
let arr = new Demo(1, 2);
arr.push(3);    // [1, 2, 3]

小結

  • class 繼承機制和 es5 不同, 在子類的 constructor 中要首先拿到父類 superthis, 而 es5 的是先創建 this;
  • class 的繼承相對於 es5 的繼承實現起來比較簡單清晰, 能夠繼承 js 原生構造器;
  • class 內部定義的的方法均是不可見的;

ES6中的Class