摘要:生成的類的原型會被自動調整,而你還能調用方法來訪問基類的構造器。唯一能避免調用的辦法,是從類構造器中返回一個對象。
起源
JS 從創建之初就不支持類,也沒有把類繼承作為定義相似對象以及關聯對象的主要方式,這讓不少開發者感到困惑。而從 ES1 誕生之前直到ES5 時期,很多庫都創建了一些工具,讓 JS 顯得貌似能支持類。盡管一些 JS 開發者強烈認為這門語言不需要類,但為處理類而創建的代碼庫如此之多,導致 ES6 最終引入了類。
ES5 中的仿類結構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本質是一種語法糖,而使用類實現的繼承其本質上就是原型的繼承.
為何要使用類的語法類聲明不會被提升,這與函數定義不同。類聲明的行為與 let 相似,因此在程序的執行到達聲明處之前,類會存在于暫時性死區內。
類聲明中的所有代碼會自動運行在嚴格模式下,并且也無法退出嚴格模式。
調用類構造器時不使用 new ,會拋出錯誤。
試圖在類的方法內部重寫類名,會拋出錯誤。
作為一級公民的類在編程中,能被當作值來使用的就稱為一級公民( first-class citizen ),意味著它能作為參
數傳給函數、能作為函數返回值、能用來給變量賦值。 JS的函數就是一級公民(它們有時又
被稱為一級函數),此特性讓 JS 獨一無二
ES6 延續了傳統,讓類同樣成為一級公民。這就使得類可以被多種方式所使用。例如,它能
作為參數傳入函數:
function createObject(classDef) { return new classDef(); } let obj = createObject(class { sayHi() { console.log("Hi!"); } }); obj.sayHi(); // "Hi!使用派生類進行繼承
ES6 之前,實現自定義類型的繼承是個繁瑣的過程。嚴格的繼承要求有多個步驟。例如,研
究以下范例:
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
的新手,并會成為有經驗開發者出錯的根源之一。
類讓繼承工作變得更輕易,使用熟悉的 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使用 super() 時需牢記以下幾點:
你只能在派生類中使用 super() 。若嘗試在非派生的類(即:沒有使用 extends關鍵字的類)或函數中使用它,就會拋出錯誤。
在構造器中,你必須在訪問 this 之前調用 super() 。由于 super() 負責初始化this ,因此試圖先訪問 this 自然就會造成錯誤。
唯一能避免調用 super() 的辦法,是從類構造器中返回一個對象。
總結ES6 的類讓 JS 中的繼承變得更簡單,因此對于你已從其他語言學習到的類知識,你無須將其
丟棄。 ES6 的類起初是作為 ES5 傳統繼承模型的語法糖,但添加了許多特性來減少錯誤。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/43515.html
摘要:歡迎關注我的博客正文讓我來構造函數其實,模擬一個類的方式非常的簡單構造函數。我們先來看一個例子這里通過構造函數模擬出來的類,其實和其他語言的類行為上是基本一致的,唯一的區別就是它不具備私有方法。 前言 ES6時代的來臨,使得類繼承變得如此的圓滑。但是,你有思考過ES6的類繼承模式嗎?如何去實現它呢? 類繼承對于JavaScript來說,實現方式與Java等類語言大不相同。熟悉JavaS...
摘要:靜態屬性靜態方法目前支持靜態方法表示,類屬性及靜態屬性目前作為提案還未正式成為標準。在中,抽象類不能用來實例化對象,主要做為其它派生類的基類使用。不同于接口,抽象類可以包含成員的實現細節。中也是這樣規定的抽象類不允許直接被實例化。 嘗試重寫 在此之前,通過《JavaScript => TypeScript 入門》已經掌握了類型聲明的寫法。原以為憑著那一條無往不利的規則,就可以開開心心的...
摘要:主要知識點類聲明類表達式類的重要要點以及類繼承深入理解筆記目錄中的仿類結構在及更早版本中都不存在類。與類最接近的是創建一個構造器,然后將方法指派到該構造器的原型上。調用類構造器時不使用,會拋出錯誤。 主要知識點:類聲明、類表達式、類的重要要點以及類繼承showImg(https://segmentfault.com/img/bVbfWnV?w=933&h=662); 《深入理解ES6...
摘要:特性介紹箭頭函數是新增的特性之一,它為這門語言提供了一種全新的書寫函數的語法。用生成的函數會定義一個自己的,而箭頭函數沒有自己的,而是會和上一層的作用域共享。 本文同步自我得博客:http://www.joeray61.com JS中的箭頭 箭頭在JS里并不算是個新鮮的玩意兒,一直以來,JS都支持-->這樣的箭頭。 很早的時候有些瀏覽器還不支持JS,當時的人們為了兼容這些瀏覽器,需要這...
閱讀 2928·2023-04-25 19:08
閱讀 1420·2021-11-16 11:45
閱讀 1975·2021-10-13 09:40
閱讀 4141·2021-09-30 09:47
閱讀 2418·2019-08-30 15:44
閱讀 2282·2019-08-30 13:03
閱讀 1393·2019-08-30 12:56
閱讀 1894·2019-08-26 14:04