JS 從建立之初就不支持類,也沒有把類繼承做爲定義類似對象以及關聯對象的主要方式,這讓很多開發者感到困惑。而從 ES1 誕生以前直到ES5 時期,不少庫都建立了一些工具,讓 JS 顯得貌似能支持類。儘管一些 JS 開發者強烈認爲這門語言不須要類,但爲處理類而建立的代碼庫如此之多,致使 ES6 最終引入了類。es6
JS 在 ES5 及更早版本中都不存在類。與類最接近的是:建立一個構造器,而後將方法指派到
該構造器的原型上。這種方式一般被稱爲建立一個自定義類型。例如:編程
function PersonType(name) { this.name = name; } PersonType.prototype.sayName = function() { console.log(this.name); }; let person = new PersonType("Nicholas"); person.sayName(); // 輸出 "Nicholas" console.log(person instanceof PersonType); // true console.log(person instanceof Object); // true
此代碼中的 PersonType 是一個構造器函數,並建立了單個屬性 name 。 sayName() 方法被
指派到原型上,所以在 PersonType 對象的全部實例上都共享了此方法。接下來,使用 new
運算符建立了 PersonType 的一個新實例 person ,此對象會被認爲是一個經過原型繼承了
PersonType 與 Object 的實例。
這種基本模式在許多對類進行模擬的 JS 庫中都存在,而這也是 ES6 類的出發點。函數
類聲明以 class 關鍵字開始,其後是類的名稱;剩餘部分的語法看起來就像對象字面量中的
方法簡寫,而且在方法之間不須要使用逗號。做爲範例,此處有個簡單的類聲明:工具
class PersonClass { // 等價於 PersonType 構造器 constructor(name) { this.name = name; } // 等價於 PersonType.prototype.sayName sayName() { console.log(this.name); } } let person = new PersonClass("Nicholas"); person.sayName(); // 輸出 "Nicholas" console.log(person instanceof PersonClass); // true console.log(person instanceof Object); // true console.log(typeof PersonClass); // "function" console.log(typeof PersonClass.prototype.sayName); // "function"
es6中類關鍵字class本質是一種語法糖,而使用類實現的繼承其本質上就是原型的繼承.學習
在編程中,能被看成值來使用的就稱爲一級公民( first-class citizen ),意味着它能做爲參
數傳給函數、能做爲函數返回值、能用來給變量賦值。 JS的函數就是一級公民(它們有時又
被稱爲一級函數),此特性讓 JS 獨一無二
ES6 延續了傳統,讓類一樣成爲一級公民。這就使得類能夠被多種方式所使用。例如,它能
做爲參數傳入函數:this
function createObject(classDef) { return new classDef(); } let obj = createObject(class { sayHi() { console.log("Hi!"); } }); obj.sayHi(); // "Hi!
ES6 以前,實現自定義類型的繼承是個繁瑣的過程。嚴格的繼承要求有多個步驟。例如,研
究如下範例:prototype
function Rectangle(length, width) { this.length = length; this.width = width; } Rectangle.prototype.getArea = function() { return this.length * this.width; }; function Square(length) { Rectangle.call(this, length, length); } Square.prototype = Object.create(Rectangle.prototype, { constructor: { value:Square, enumerable: true, writable: true, configurable: true } }); var square = new Square(3); console.log(square.getArea()); // 9 console.log(square instanceof Square); // true console.log(square instanceof Rectangle); // true
Square 繼承了 Rectangle ,爲此它必須使用 Rectangle.prototype 所建立的一個新對象來
重寫 Square.prototype ,而且還要調用 Rectangle.call() 方法。這些步驟經常會搞暈 JS
的新手,並會成爲有經驗開發者出錯的根源之一。code
類讓繼承工做變得更輕易,使用熟悉的 extends 關鍵字來指定當前類所須要繼承的函數,即
可。生成的類的原型會被自動調整,而你還能調用 super() 方法來訪問基類的構造器。此處
是與上個例子等價的 ES6 代碼:對象
class Rectangle { constructor(length, width) { this.length = length; this.width = width; } getArea() { return this.length * this.width; } } class Square extends Rectangle { constructor(length) { // 與 Rectangle.call(this, length, length) 相同 super(length, length); } } var square = new Square(3); console.log(square.getArea()); // 9 console.log(square instanceof Square); // true console.log(square instanceof Rectangle); // true
ES6 的類讓 JS 中的繼承變得更簡單,所以對於你已從其餘語言學習到的類知識,你無須將其
丟棄。 ES6 的類起初是做爲 ES5 傳統繼承模型的語法糖,但添加了許多特性來減小錯誤。繼承