摘要:主要知識(shí)點(diǎn)類聲明類表達(dá)式類的重要要點(diǎn)以及類繼承深入理解筆記目錄中的仿類結(jié)構(gòu)在及更早版本中都不存在類。與類最接近的是創(chuàng)建一個(gè)構(gòu)造器,然后將方法指派到該構(gòu)造器的原型上。調(diào)用類構(gòu)造器時(shí)不使用,會(huì)拋出錯(cuò)誤。
主要知識(shí)點(diǎn):類聲明、類表達(dá)式、類的重要要點(diǎn)以及類繼承
《深入理解ES6》筆記 目錄
ES5 中的仿類結(jié)構(gòu)JS 在 ES5 及更早版本中都不存在類。與類最接近的是:創(chuàng)建一個(gè)構(gòu)造器,然后將方法指派到該構(gòu)造器的原型上。這種方式通常被稱為創(chuàng)建一個(gè)自定義類型:
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 關(guān)鍵字開始,其后是類的名稱;剩余部分的語(yǔ)法看起來就像對(duì)象字面量中的方法簡(jiǎn)寫,并且在方法之間不需要使用逗號(hào):
class PersonClass { // 等價(jià)于 PersonType 構(gòu)造器,自有屬性 constructor(name) { this.name = name; } // 等價(jià)于 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"類聲明和函數(shù)聲明的區(qū)別和特點(diǎn)
類聲明不會(huì)被提升,這與函數(shù)定義不同。類聲明的行為與 let 相似,因此在程序的執(zhí)行到達(dá)聲明處之前,類會(huì)存在于暫時(shí)性死區(qū)內(nèi)。
類聲明中的所有代碼會(huì)自動(dòng)運(yùn)行在嚴(yán)格模式下,并且也無法退出嚴(yán)格模式。
類的所有方法都是不可枚舉的,這是對(duì)于自定義類型的顯著變化,后者必須用Object.defineProperty() 才能將方法改變?yōu)椴豢擅杜e。
類的所有方法內(nèi)部都沒有 [[Construct]] ,因此使用 new 來調(diào)用它們會(huì)拋出錯(cuò)誤。
調(diào)用類構(gòu)造器時(shí)不使用 new ,會(huì)拋出錯(cuò)誤。
試圖在類的方法內(nèi)部重寫類名,會(huì)拋出錯(cuò)誤。
用ES5實(shí)現(xiàn)剛才的類的功能:
// 直接等價(jià)于 PersonClass let PersonType2 = (function() { "use strict"; //確保在類的內(nèi)部不可以重寫類名 const PersonType2 = function(name) { // 確認(rèn)函數(shù)被調(diào)用時(shí)使用了 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() { // 確認(rèn)函數(shù)被調(diào)用時(shí)沒有使用 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; }());
此例說明了盡管不使用新語(yǔ)法也能實(shí)現(xiàn)類的任何特性,但類語(yǔ)法顯著簡(jiǎn)化了所有功能的代碼。
類表達(dá)式類與函數(shù)有相似之處,即它們都有兩種形式:聲明與表達(dá)式。
//聲明式 class B { constructor() {} } //匿名表達(dá)式 let PersonClass = class { // 等價(jià)于 PersonType 構(gòu)造器 constructor(name) { this.name = name; } // 等價(jià)于 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" //命名表達(dá)式,B可以在外部使用,而B1只能在內(nèi)部使用 let PersonClass = class PersonClass2 { // 等價(jià)于 PersonType 構(gòu)造器 constructor(name) { this.name = name; } // 等價(jià)于 PersonType.prototype.sayName sayName() { console.log(this.name); } }; console.log(typeof PersonClass); // "function" console.log(typeof PersonClass2); // "undefined",只有在類內(nèi)部才可以訪問到作為一級(jí)公民的類
在編程中,能被當(dāng)作值來使用的就稱為一級(jí)公民( first-class citizen ),意味著它能作為參數(shù)傳給函數(shù)、能作為函數(shù)返回值、能用來給變量賦值。
作為參數(shù)傳入函數(shù):
function createObject(classDef) { return new classDef(); } let obj = createObject(class { sayHi() { console.log("Hi!"); } }); obj.sayHi(); // "Hi!"
通過立即調(diào)用類構(gòu)造函數(shù)可以創(chuàng)建單例:
//使用 new 來配合類表達(dá)式,并在表達(dá)式后面添加括號(hào) let person = new class { constructor(name) { this.name = name; } sayName() { console.log(this.name); } }("Nicholas"); person.sayName(); // "Nicholas"訪問器屬性
自有屬性需要在類構(gòu)造器中創(chuàng)建,而類還允許你在原型上定義訪問器屬性:
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
非類的等價(jià)表示如下:
// 直接等價(jià)于上個(gè)范例 let CustomHTMLElement = (function() { "use strict"; const CustomHTMLElement = function(element) { // 確認(rèn)函數(shù)被調(diào)用時(shí)使用了 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; }());需計(jì)算的成員名
無須使用標(biāo)識(shí)符,而是用方括號(hào)來包裹一個(gè)表達(dá)式:
let methodName = "sayName"; class PersonClass { constructor(name) { this.name = name; } [methodName]() { console.log(this.name); } } let me = new PersonClass("Nicholas"); me.sayName(); // "Nicholas"
訪問器屬性能以相同方式使用需計(jì)算的名稱,就像這樣:
let propertyName = "html"; class CustomHTMLElement { constructor(element) { this.element = element; } get [propertyName]() { return this.element.innerHTML; } set [propertyName](value) { this.element.innerHTML = value; } }生成器方法
你已學(xué)會(huì)如何在對(duì)象字面量上定義一個(gè)生成器:只要在方法名稱前附加一個(gè)星號(hào)( * )。這一語(yǔ)法對(duì)類同樣有效,允許將任何方法變?yōu)橐粋€(gè)生成器:
class MyClass { *createIterator() { yield 1; yield 2; yield 3; } } let instance = new MyClass(); let iterator = instance.createIterator();靜態(tài)成員
直接在構(gòu)造器上添加額外方法來模擬靜態(tài)成員,這在 ES5 及更早版本中是另一個(gè)通用的模式:
function PersonType(name) { this.name = name; } // 靜態(tài)方法 PersonType.create = function(name) { return new PersonType(name); }; // 實(shí)例方法 PersonType.prototype.sayName = function() { console.log(this.name); }; var person = PersonType.create("Nicholas");
ES6 的類簡(jiǎn)化了靜態(tài)成員的創(chuàng)建,只要在方法與訪問器屬性的名稱前添加正式的 static 標(biāo)注:
class PersonClass { // 等價(jià)于 PersonType 構(gòu)造器 constructor(name) { this.name = name; } // 等價(jià)于 PersonType.prototype.sayName sayName() { console.log(this.name); } // 等價(jià)于 PersonType.create static create(name) { return new PersonClass(name); } } let person = PersonClass.create("Nicholas");
和普通方法不一樣的是,static修飾的方法不能在實(shí)例中訪問,只能在類中直接訪問。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/96967.html
摘要:新建一個(gè)類該函數(shù)返回一個(gè)類的實(shí)例給函數(shù)傳入通過立即調(diào)用類構(gòu)造函數(shù)可以創(chuàng)建單例。派生類是指繼承自其它類的新類。在構(gòu)造函數(shù)中訪問之前要調(diào)用,負(fù)責(zé)初始化。在構(gòu)造函數(shù)中使用通常表示當(dāng)前的構(gòu)造函數(shù)名。 ES5中的近類結(jié)構(gòu) ES5以及之前的版本,沒有類的概念,但是聰明的JavaScript開發(fā)者,為了實(shí)現(xiàn)面向?qū)ο?,?chuàng)建了特殊的近類結(jié)構(gòu)。 ES5中創(chuàng)建類的方法:新建一個(gè)構(gòu)造函數(shù),定義一個(gè)方法并且賦值...
摘要:新建一個(gè)類該函數(shù)返回一個(gè)類的實(shí)例給函數(shù)傳入通過立即調(diào)用類構(gòu)造函數(shù)可以創(chuàng)建單例。派生類是指繼承自其它類的新類。在構(gòu)造函數(shù)中訪問之前要調(diào)用,負(fù)責(zé)初始化。在構(gòu)造函數(shù)中使用通常表示當(dāng)前的構(gòu)造函數(shù)名。 ES5中的近類結(jié)構(gòu) ES5以及之前的版本,沒有類的概念,但是聰明的JavaScript開發(fā)者,為了實(shí)現(xiàn)面向?qū)ο?,?chuàng)建了特殊的近類結(jié)構(gòu)。 ES5中創(chuàng)建類的方法:新建一個(gè)構(gòu)造函數(shù),定義一個(gè)方法并且賦值...
摘要:最近買了深入理解的書籍來看,為什么學(xué)習(xí)這么久還要買這本書呢主要是看到核心團(tuán)隊(duì)成員及的創(chuàng)造者為本書做了序,作為一個(gè)粉絲,還是挺看好這本書能給我?guī)硪粋€(gè)新的升華,而且本書的作者也非常厲害。 使用ES6開發(fā)已經(jīng)有1年多了,以前看的是阮一峰老師的ES6教程,也看過MDN文檔的ES6語(yǔ)法介紹。 最近買了《深入理解ES6》的書籍來看,為什么學(xué)習(xí)ES6這么久還要買這本書呢?主要是看到Daniel A...
閱讀 3315·2021-09-23 11:55
閱讀 2674·2021-09-13 10:33
閱讀 1693·2019-08-30 15:54
閱讀 3118·2019-08-30 15:54
閱讀 2384·2019-08-30 10:59
閱讀 2393·2019-08-29 17:08
閱讀 1823·2019-08-29 13:16
閱讀 3611·2019-08-26 12:25