1. 程式人生 > >ES6快速入門(三)類與模組

ES6快速入門(三)類與模組

類與模組

一、類

一)類的宣告

class Person {
    constructor(name) {
        this.name = name;
    }
    sayName() {
        console.log(this.name);
    }
}

let tom = new Person('Tom');
tom.sayName(); //Tom
console.log(tom instanceof Person); //true
console.log(tom instanceof Object); //true
console.log(typeof Person); //
function

自有屬性:屬性只出現在例項而不是在原型上,而且只能由建構函式和方法來建立。

差異:

1. 類宣告和函式定義不同,它們是不會被提升的。類宣告的行為和 let 比較相似,所以當執
行流作用到類宣告之前類會存在於暫存性死區(temporal dead zone) 內。
2. 類宣告中的程式碼自動執行在嚴格模式下,同時沒有任何辦法可以手動切換到非嚴格模
式。
3. 所有的方法都是不可列舉的(non-enumerable) ,這和自定義型別相比是個顯著的差
異,因為後者需要使用 Object.defineProperty() 才能定義不可列舉的方法。
4. 所有的方法都不能使用 new 來呼叫,因為它們沒有內部方法 [[Construct]]
5. 不使用 new 來呼叫類建構函式會丟擲錯誤。
6. 試圖在方法內部重寫類名的行為會丟擲錯誤。 

二)類表示式

設計類表示式的目的主要是為了將它賦值給變數或者傳參給函式。

//不會被提升
let Person = class {
    constructor(name) {
        this.name = name;
    }

    sayName() {
        console.log(this.name);
    }
};

三)作為一等公民的類

在程式設計中,如果某些東西能作為值使用,那麼它就被稱為一等公民。ES6中類也是一等公民:

function createPerson(person) {
    return new person();
}
let tom 
= createPerson(class { sayHi() { console.log('Hi'); } }); tom.sayHi(); //Hi

類表示式另一個有趣的使用方式是通過立即呼叫(immediately invoking) 類建構函式來建立單例(singleton):

let tom = new class {
    constructor(name) {
        this.name = name;
    }
    sayName() {
        console.log(`My name is ${this.name}`);
    }
}('Tom');
tom.sayName();

四)訪問器屬性

class Person {
    constructor(name) {
        this.name = name;
    }
    //這裡不能用get phone(){}
    get phone2() {
        return this.phone;
    }
    set phone2(phoneNumber) {
        this.phone = phoneNumber;
    }
}
let price = new Person('Price', 112);
price.name = 'Price2';
price.phone = 119;
console.log(`His name is ${price.name} and his phone number is ${price.phone}`);

五)靜態成員

//靜態成員不能被例項訪問。你必須通過類本身來使用它們。
class Person {
    constructor(name) {
        this.name = name;
    }
    sayName() {
        console.log(this.name)
    }
    //等同於Person.whatIs(){}
    static whatIs() {
        return 'I am a person!';
    }
}

六)繼承

class Worker extends Person {
    /*如果在派生類中定義 constructor 則必須使用super(),
    否則會發生錯誤。如果你選擇不使用 constructor,
    那麼會自動呼叫 super() 和傳入建構函式的引數以建立類的例項*/
    constructor(name, age) {
        super(name);
        this.age = age;
    }
    //注意
    syaName() {
        super.sayName();
        console.log(`My name is ${this.name}`);
    }
    sayAge (){
        console.log(`I am ${this.age}`)
    }
}

let jimmy = new Worker('Jimmy', 2);
jimmy.sayAge(); //I am 2
jimmy.syaName(); //Jimmy   My name is Jimmy

注意: 使用 super() 需要牢記以下幾點:
1. 你只能在派生類中使用 super(),否則(沒有使用 extends 的類或函式) 一個錯誤會
被丟擲。
2. 你必須在建構函式的起始位置呼叫 super(),因為它會初始化 this。任何在 super()
之前訪問 this 的行為都會造成錯誤。
3. 在類建構函式中,唯一能避免呼叫 super() 的辦法是返回一個物件。

ECMAScript 6 派生類最強大的地方在於它們可以繼承一個表示式。只要該表示式的計算
結果包含 [[Construct]] 的函式和一個原型,那麼就可以使用 extends 來繼承它。

內建物件的繼承

使用ES5很難繼承內建物件,ES6做法:

class MyArray extends Array {
}

二、模組

ECMAScript 6 之前,每個 JavaScript 檔案中定義的內容都由全域性作用域共享。
web 應用變得複雜並需要書寫更多的 JavaScript 程式碼時,上述載入方式會出現命名衝突或安全方面的問題。

模組是指採取不同於現有載入方式的 JavaScript 檔案(與 script 這種傳統的載入模式相
對) 。這種方式很有必要,因為它和 script 使用不同的語義:
1. 模組中的程式碼自動執行在嚴格模式下,並無任何辦法修改為非嚴格模式。
2. 模組中的頂級(top level) 變數不會被新增到全域性作用域中。它們只存在於各自的模組中
的頂級作用域。
3. 模組頂級作用域中的 this undefined
4. 模組不允許存在 HTML 式的註釋(JavaScript 歷史悠久的遺留特性) 。
5. 模組必須輸出可被模組外部程式碼使用的相關內容。
6. 模組可能會引入其它模組中的繫結。

模組真正的好處在於可以輸出和引入需要的繫結,而不是檔案中的所有內容。

理解輸出和引入是領悟模組與 script 之間差異的基礎。 

一)匯出(export)

其他暫略