摘要:本文參考了以下文章之前的文章新特性印象之一新語法面對對象關鍵字看上面例子就能明白。定義類的,配合創(chuàng)建新對象。繼承非構造器對象的原型是。錯誤檢查繼承的目標一定要是個對象或者。的構造器是可改寫,但不可枚舉。引入了一個標簽,負責載入模塊。
本文參考了以下文章/PPT:
Use ECMAScript 6 today
Ecmascript 6 Whats next for Javascript
ECMAScript 6: classes
ECMAScript 6 modules: the final syntax
es6features
Javascript Modules
之前的文章:
ECMAScript 6新特性印象之一:新語法
面對對象1.關鍵字 Class
class Artist { constructor(name) { this.name = name; } perform() { return this.name + " performs "; } } class Singer extends Artist { constructor(name, song) { super.constructor(name); this.song = song; } perform() { return super.perform() + "[" + this.song + "]"; } } let james = new Singer("Etta James", "At last"); james instanceof Artist; // true james instanceof Singer; // true james.perform(); // "Etta James performs [At last]"
看上面例子就能明白。注意幾個關鍵字extends,super。
雖然ES6的Class本質(zhì)上還是語法糖,但這么設計有它的目的。
在ES5中, function關鍵字承擔著三個職責:
定義函數(shù)。
定義方法屬性。
定義類的constructor,配合new創(chuàng)建新對象。
在ES6中,第2點被屬性方法定義(Method definitions)替代,第3點被Class關鍵字替代。一個關鍵字只承擔一個職責,不再是滿屏function,足夠清晰了吧?
有幾點要注意的:
類的body只能包含屬性方法,不能包含屬性值。屬性值放到constructor方法里。
屬性方法可以是生成器,在方法名前家*就可以。
聲明類(Class Declaration)并不會被提升(hoisted)。
如果沒有指定constructor,那會有個默認調(diào)用super的。
2.繼承 Extending
繼承的幾種情況和規(guī)則:
不要繼承空類, class Foo {},因為:
Foo的原型(prototype)是Function.prototype(所有函數(shù)的原型都是這個)。
而Foo.prototype的原型是Object.prototype。
這種繼承就和函數(shù)一樣了。
繼承null:class Foo extends null {}
Foo的原型是Function.prototype。
Foo.prototype的原型是null。
這樣Object.prototype的屬性方法都不會繼承到Foo中。
繼承構造器:class Foo extends SomeClass
Foo的原型是SomeClass。
Foo.prototype的SomeClass.prototype。
這樣,類方法屬性也會被繼承。
繼承非構造器(對象):class Foo extends SomeObject
Foo的原型是Function.prototype。
Foo.prototype的SomeClass。
錯誤檢查:繼承的目標一定要是個對象或者null。如果是繼承構造器,那么構造器的原型一定要是個對象或者null。
類聲明其實創(chuàng)建的是可變let綁定(binding,函數(shù)式編程會比較熟悉這個概念)。對于一個類Foo:
Foo的原型是不可改寫,且不可枚舉的。
Foo的構造器是可改寫,但不可枚舉。
Foo的原型函數(shù)(Foo.prototype.*)是可改寫,但不可枚舉。
模塊ES6的內(nèi)置模塊系統(tǒng)借鑒了CommonJS和AMD各自的優(yōu)點:
具有CommonJS的精簡語法、唯一導出出口(single exports)和循環(huán)依賴(cyclic dependencies)的特點。
類似AMD,支持異步加載和可配置的模塊加載。
不僅僅借鑒,ES6還對這些功能進行了優(yōu)化:
語法比CommonJS更精簡。
支持結構的靜態(tài)分析(靜態(tài)檢查,優(yōu)化等等)。
循環(huán)依賴的支持比CommonJS更好。
1.語法
ES6模塊的導出出口形式有兩種:命名導出(一個模塊多個導出)、標準導出(一個模塊一個導出)。
命名導出 Named exports
//-------lib.js---------- export const sqrt = Math.sqrt; export function square(x) { return x * x; } export function diag(x, y) { return sqrt(square(x) + square(y)); } //-------main1.js-------- import { sqaure, diag } from "lib"; console.log(square(11)); // 121 console.log(diag(3,4)); // 5 //或者這樣,命名導入的名稱: //-------main2.js-------- import * as lib from "lib"; console.log(lib.square(11)); // 121 console.log(lib.diag(3,4)); // 5
標準導出 Default exports
//-------MyClass.js----- // 注意,`export`的操作對象是表達式,一般是沒有名字的。 export default class { ... }; //-------main3.js-------- // 通過模塊名字識別 import MyClass from "MyClass"; let inst = new MyClass();
當然,這兩種導出也可以混合使用。本質(zhì)上,標準導出只是指名導出的一種,名稱是「default」而已。
就目前了解的來看,ES6的模塊導出貌似有些繁瑣,還不如CommonJS直接通過object導出利索。
2.設計初衷 Design goals
TC39在討論ES6的模塊化問題時,主要考慮了下面幾點:
直接導出優(yōu)先
靜態(tài)模塊結構
同步/異步載入都要支持
支持循環(huán)依賴
第一點就是要簡單已用。而靜態(tài)模塊結構更多是出于性能優(yōu)化、靜態(tài)類型檢查(沒錯,就是這個,動態(tài)語言為什么要有這個,其實還是為了性能)和以后的可能會加入的「宏模板」功能。
3.更多導入/導出寫法舉例
導入:
// 標準導入,命名導入 import theDefault, { named1, named2 } from "src/mylib"; import theDefault from from "src/mylib"; import { named1, named2 } from "src/mylib"; // 重命名 import { named1 as myNamed1, named2 } from "src/mylib"; // 將導入的模塊定義為一個對象 // 模塊的每個屬性都是該對象的同名方法屬性 import * as mylib from "src/mylib"; // 僅讀取模塊,不導入任何功能 import "src/mylib";
導出:
// 使用關鍵字**export**導出 export let myVar1 = ...; export function MyFunc() {...} export function* myGeneratorFunc() {...} // 也可以以對象形式導出 const MY_CONST = ...; function myFunc() { ... } export { MY_CONST, myFunc } // 當然,名字不一定要相同 export { MY_CONST as THE_CONST, myFunc as theFunc }; // 支持重導出,即在當前模塊導出其他模塊的功能 方便hack export * from "src/other_module"; export { foo, bar } from "src/other_module";
上面說的這些語法,普通的