摘要:主要知識點類聲明類表達式類的重要要點以及類繼承深入理解筆記目錄中的仿類結構在及更早版本中都不存在類。與類最接近的是創建一個構造器,然后將方法指派到該構造器的原型上。調用類構造器時不使用,會拋出錯誤。
主要知識點:類聲明、類表達式、類的重要要點以及類繼承
《深入理解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類的聲明 基本的類聲明
類聲明以 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"類聲明和函數聲明的區別和特點
類聲明不會被提升,這與函數定義不同。類聲明的行為與 let 相似,因此在程序的執行到達聲明處之前,類會存在于暫時性死區內。
類聲明中的所有代碼會自動運行在嚴格模式下,并且也無法退出嚴格模式。
類的所有方法都是不可枚舉的,這是對于自定義類型的顯著變化,后者必須用Object.defineProperty() 才能將方法改變為不可枚舉。
類的所有方法內部都沒有 [[Construct]] ,因此使用 new 來調用它們會拋出錯誤。
調用類構造器時不使用 new ,會拋出錯誤。
試圖在類的方法內部重寫類名,會拋出錯誤。
用ES5實現剛才的類的功能:
// 直接等價于 PersonClass let PersonType2 = (function() { "use strict"; //確保在類的內部不可以重寫類名 const PersonType2 = function(name) { // 確認函數被調用時使用了 new if (typeof new.target === "undefined") { throw new Error("Constructor must be called with new."); } this.name = name; } Object.defineProperty(PersonType2.prototype, "sayName", { value: function() { // 確認函數被調用時沒有使用 new if (typeof new.target !== "undefined") { throw new Error("Method cannot be called with new."); } console.log(this.name); }, //定義為不可枚舉 enumerable: false, writable: true, configurable: true }); return PersonType2; }());
此例說明了盡管不使用新語法也能實現類的任何特性,但類語法顯著簡化了所有功能的代碼。
類表達式類與函數有相似之處,即它們都有兩種形式:聲明與表達式。
//聲明式 class B { constructor() {} } //匿名表達式 let PersonClass = class { // 等價于 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" //命名表達式,B可以在外部使用,而B1只能在內部使用 let PersonClass = class PersonClass2 { // 等價于 PersonType 構造器 constructor(name) { this.name = name; } // 等價于 PersonType.prototype.sayName sayName() { console.log(this.name); } }; console.log(typeof PersonClass); // "function" console.log(typeof PersonClass2); // "undefined",只有在類內部才可以訪問到作為一級公民的類
在編程中,能被當作值來使用的就稱為一級公民( first-class citizen ),意味著它能作為參數傳給函數、能作為函數返回值、能用來給變量賦值。
作為參數傳入函數:
function createObject(classDef) { return new classDef(); } let obj = createObject(class { sayHi() { console.log("Hi!"); } }); obj.sayHi(); // "Hi!"
通過立即調用類構造函數可以創建單例:
//使用 new 來配合類表達式,并在表達式后面添加括號 let person = new class { constructor(name) { this.name = name; } sayName() { console.log(this.name); } }("Nicholas"); person.sayName(); // "Nicholas"訪問器屬性
自有屬性需要在類構造器中創建,而類還允許你在原型上定義訪問器屬性:
class CustomHTMLElement { constructor(element) { this.element = element; } get html() { return this.element.innerHTML; } set html(value) { this.element.innerHTML = value; } } var descriptor = Object.getOwnPropertyDescriptor(CustomHTMLElement.prototype, "html"); console.log("get" in descriptor); // true console.log("set" in descriptor); // true console.log(descriptor.enumerable); // false
非類的等價表示如下:
// 直接等價于上個范例 let CustomHTMLElement = (function() { "use strict"; const CustomHTMLElement = function(element) { // 確認函數被調用時使用了 new if (typeof new.target === "undefined") { throw new Error("Constructor must be called with new."); } this.element = element; } Object.defineProperty(CustomHTMLElement.prototype, "html", { enumerable: false, configurable: true, get: function() { return this.element.innerHTML; }, set: function(value) { this.element.innerHTML = value; } }); return CustomHTMLElement; }());需計算的成員名
無須使用標識符,而是用方括號來包裹一個表達式:
let methodName = "sayName"; class PersonClass { constructor(name) { this.name = name; } [methodName]() { console.log(this.name); } } let me = new PersonClass("Nicholas"); me.sayName(); // "Nicholas"
訪問器屬性能以相同方式使用需計算的名稱,就像這樣:
let propertyName = "html"; class CustomHTMLElement { constructor(element) { this.element = element; } get [propertyName]() { return this.element.innerHTML; } set [propertyName](value) { this.element.innerHTML = value; } }生成器方法
你已學會如何在對象字面量上定義一個生成器:只要在方法名稱前附加一個星號( * )。這一語法對類同樣有效,允許將任何方法變為一個生成器:
class MyClass { *createIterator() { yield 1; yield 2; yield 3; } } let instance = new MyClass(); let iterator = instance.createIterator();靜態成員
直接在構造器上添加額外方法來模擬靜態成員,這在 ES5 及更早版本中是另一個通用的模式:
function PersonType(name) { this.name = name; } // 靜態方法 PersonType.create = function(name) { return new PersonType(name); }; // 實例方法 PersonType.prototype.sayName = function() { console.log(this.name); }; var person = PersonType.create("Nicholas");
ES6 的類簡化了靜態成員的創建,只要在方法與訪問器屬性的名稱前添加正式的 static 標注:
class PersonClass { // 等價于 PersonType 構造器 constructor(name) { this.name = name; } // 等價于 PersonType.prototype.sayName sayName() { console.log(this.name); } // 等價于 PersonType.create static create(name) { return new PersonClass(name); } } let person = PersonClass.create("Nicholas");
和普通方法不一樣的是,static修飾的方法不能在實例中訪問,只能在類中直接訪問。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/96967.html
摘要:新建一個類該函數返回一個類的實例給函數傳入通過立即調用類構造函數可以創建單例。派生類是指繼承自其它類的新類。在構造函數中訪問之前要調用,負責初始化。在構造函數中使用通常表示當前的構造函數名。 ES5中的近類結構 ES5以及之前的版本,沒有類的概念,但是聰明的JavaScript開發者,為了實現面向對象,創建了特殊的近類結構。 ES5中創建類的方法:新建一個構造函數,定義一個方法并且賦值...
摘要:新建一個類該函數返回一個類的實例給函數傳入通過立即調用類構造函數可以創建單例。派生類是指繼承自其它類的新類。在構造函數中訪問之前要調用,負責初始化。在構造函數中使用通常表示當前的構造函數名。 ES5中的近類結構 ES5以及之前的版本,沒有類的概念,但是聰明的JavaScript開發者,為了實現面向對象,創建了特殊的近類結構。 ES5中創建類的方法:新建一個構造函數,定義一個方法并且賦值...
摘要:最近買了深入理解的書籍來看,為什么學習這么久還要買這本書呢主要是看到核心團隊成員及的創造者為本書做了序,作為一個粉絲,還是挺看好這本書能給我帶來一個新的升華,而且本書的作者也非常厲害。 使用ES6開發已經有1年多了,以前看的是阮一峰老師的ES6教程,也看過MDN文檔的ES6語法介紹。 最近買了《深入理解ES6》的書籍來看,為什么學習ES6這么久還要買這本書呢?主要是看到Daniel A...
閱讀 3255·2021-09-23 11:55
閱讀 2587·2021-09-13 10:33
閱讀 1656·2019-08-30 15:54
閱讀 3085·2019-08-30 15:54
閱讀 2357·2019-08-30 10:59
閱讀 2361·2019-08-29 17:08
閱讀 1793·2019-08-29 13:16
閱讀 3582·2019-08-26 12:25