JS?class語(yǔ)法糖的深入剖析
引言
在很早以前,寫(xiě)過(guò)一篇文章 “類(lèi)”設(shè)計(jì)模式和“原型”設(shè)計(jì)模式——“復(fù)制”和“委托”的差異 ,大致意思就是說(shuō):代碼復(fù)用,也就是繼承、重寫(xiě),有兩種思路:1. 面向?qū)ο蟮念?lèi)繼承;2. 基于 JavaScript 原型鏈的原型繼承;前者的主要特點(diǎn)是:復(fù)制,通俗來(lái)說(shuō)就是把變量、屬性再?gòu)?fù)制一份,后者的主要特點(diǎn)是:委托,通過(guò)屬性的查找來(lái)實(shí)現(xiàn)的。
后來(lái)呢,深入了解 JavaScript 高級(jí)程序設(shè)計(jì)中的繼承,包括構(gòu)造函數(shù)繼承、原型繼承、組合繼承、寄生組合繼承,都有各自的缺點(diǎn),有興趣的朋友,可以看我這篇文章。
還有,本瓜特別記?。壕S基對(duì) JavaScript 起源的解釋
JavaScript的語(yǔ)言設(shè)計(jì)主要受到了Self(一種基于原型的編程語(yǔ)言)和Scheme(一門(mén)函數(shù)式編程語(yǔ)言)的影響。在語(yǔ)法結(jié)構(gòu)上它又與C語(yǔ)言有很多相似。
最后,我的小結(jié)呢就是:JavaScript 本身的設(shè)計(jì)就是“通過(guò)原型委托”來(lái)實(shí)現(xiàn)代碼復(fù)用的,結(jié)果 ES6 搞出了個(gè) class 作為語(yǔ)法糖,其本身還是基于原型鏈,但又是為了實(shí)現(xiàn)面向?qū)ο?,面向?qū)ο笫腔?class 類(lèi)那種“復(fù)制”來(lái)實(shí)現(xiàn)代碼復(fù)用。
類(lèi) 和 原型,是兩種不同的東西,JS class 將二者混在了一起,別不別扭?
后來(lái)也看到一些文章說(shuō)在 JS 中使用 class 類(lèi)會(huì)造成一些困擾,所以更加堅(jiān)定要減少使用 class 。
而實(shí)際上,本篇題目是:JS class 并不只是簡(jiǎn)單的語(yǔ)法糖,所以,本篇并不是為了說(shuō)它不好,而是要說(shuō)它的好的!
來(lái)吧,展翅!
class 第一個(gè)好:私有變量
如果不用 class , 還有什么更優(yōu)雅的方法實(shí)現(xiàn)以下子類(lèi)的私有變量嗎?
class Person {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
} // Person.constructor
get FullName () {
return this.firstName + " " + this.lastName;
}
} // Person
class Employee extends Person {
#salary;
constructor(firstName, lastName, salary) {
super(firstName, lastName);
this.salary = salary;
}
get salary() {
return this.#salary;
}
set salary(salary) {
this.#salary = salary;
console.log("Salary changed for " + this.fullName + " : $" + this.salary);
}
} // Employee
設(shè)想下,我們用原型鏈的思路模擬(對(duì)象):
const Person = {
set givenName(givenName) {
this._givenName = givenName;
},
set familyName(familyName) {
this._familyName = familyName;
},
get fullName() {
return `${this._givenName} ${this._familyName}`;
}
};
const test = Person; // 這里假設(shè)用 對(duì)象 模擬 類(lèi)
test.givenName = "Joe";
test.familyName = "Martinez";
console.log("test.fullName", test.fullName); // Joe Martinez
console.log("test.givenName", test.givenName); // undefined
console.log("test._givenName", test._givenName); // Joe
沒(méi)有實(shí)現(xiàn)私有屬性 _givenName
而 class 可以將值存為私有,使得對(duì)象外部不能修改:
class 第二個(gè)好:super 繼承
class 可以通過(guò) super 更優(yōu)雅的實(shí)現(xiàn)繼承、和重寫(xiě),比如:
class Cash {
constructor() {
this.total = 0;
}
add(amount) {
this.total += amount;
if (this.total < 0) this.total = 0;
}
} // Cash
class Nickles extends Cash {
add(amount) {
super.add(amount * 5);
}
} // Nickles
如果是按照老樣子,原型鏈,它可能是這樣的:
const Cash = function() {
this.total = 0;
}; // Cash
Cash.prototype = {
add : function(amount) {
this.total += amount;
if (this.total < 0) this.total = 0;
}
}; // Cash.prototype
const Nickles = function() {
Object.assign(this, new Cash());
this.add = function(amount) {
Cash.add.apply(this, amount);
};
} // Nickles
讀起來(lái)有點(diǎn)亂,this 指來(lái)指去,還有在構(gòu)造函數(shù)中手動(dòng)做的 assign 操作,這會(huì)增加代碼執(zhí)行耗時(shí)。
綜上兩點(diǎn),JS class 還是非常有使用它的價(jià)值的,不用逃避,把它用在合適的場(chǎng)景,肯定會(huì)發(fā)現(xiàn)其魅力~~
以上就是JS class語(yǔ)法糖的深入剖析的詳細(xì)內(nèi)容,更多關(guān)于JS class語(yǔ)法糖的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
JavaScript編程中實(shí)現(xiàn)對(duì)象封裝特性的實(shí)例講解
JavaScript可以在一定程度上以面向?qū)ο蠓绞竭M(jìn)行編程,而封裝是面向?qū)ο笾械囊粋€(gè)重要特性,本文就來(lái)分享阮一峰老師對(duì)JavaScript編程中實(shí)現(xiàn)對(duì)象封裝特性的實(shí)例講解2016-06-06
js c++ vue方法與數(shù)據(jù)交互通信示例
這篇文章主要為大家介紹了js c++ vue方法與數(shù)據(jù)交互通信示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08
JSON字符串轉(zhuǎn)換JSONObject和JSONArray的方法
這篇文章主要介紹了JSON字符串轉(zhuǎn)換JSONObject和JSONArray的方法的相關(guān)資料,需要的朋友可以參考下2016-06-06
TypeScript5.2引入新關(guān)鍵字using介紹
這篇文章主要介紹了TypeScript5.2引入新關(guān)鍵字using使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-06-06

