什么是語法糖蹂风?
語法糖(syntactic sugar)是指編程語言中可以更容易的表達(dá)一個(gè)操作的語法客冈,它可以使程序員更加容易去使用這門語言告嘲,操作可以變得更加清晰、方便华嘹,或者更加符合程序員的編程習(xí)慣吧趣。用比較通俗易懂的方式去理解就是,在之前的某個(gè)語法的基礎(chǔ)上改變了一種寫法耙厚,實(shí)現(xiàn)的功能相同强挫,但是寫法不同了,主要是為了讓開發(fā)人員在使用過程中更方便易懂薛躬。
es6中的語法糖有哪些纠拔?
這個(gè)話題其實(shí)很大,es6中的語法糖太多了泛豪,例如常用的箭頭函數(shù),解構(gòu)賦值等都是語法糖侦鹏,具體的可以看看這篇文章诡曙。
es6中的class
es5和es6構(gòu)造實(shí)例的區(qū)別
接下來就進(jìn)入正題了,揭開es6中class的神秘面紗略水。首先為什么會有class的概念价卤,在es5時(shí)期,生成實(shí)例是通過構(gòu)造函數(shù)渊涝,但是如果要添加方法的話慎璧,就必須在原型上去添加,這樣構(gòu)造函數(shù)new出來的實(shí)例才可以用這個(gè)方法跨释。就比如這樣:
// Person為構(gòu)造函數(shù)
function Person (name, age) {
this.name = name,
this.age = age
}
// 在構(gòu)造函數(shù)的原型上添加方法
Person.prototype.getName = function () {
return this.name
}
// 構(gòu)造一個(gè)實(shí)例
var huhaha = new Person('huhaha', 21)
// 在實(shí)例上調(diào)用該方法
var myName = huhaha.getName()
console.log(myname) // huhaha
那么在es6中怎么使用class去實(shí)現(xiàn)它呢胸私,先看代碼再解釋~
// 類中的this指向創(chuàng)建的實(shí)例
class Person {
constructor (name, age) {
this.name = name
this.age = age
}
getName () {
return this.name
}
}
// 構(gòu)造一個(gè)實(shí)例
let huhaha = new Person('huhaha', 21)
// 在實(shí)例上調(diào)用該方法
const myName = huhaha.getName()
console.log(myname) // huhaha
我們可以看到通過es6去實(shí)現(xiàn),更容易理解鳖谈,并且代碼量也有所減少岁疼。使用這種方式,我們可以清楚的明白缆娃,前面使用了class的就是一個(gè)類捷绒,那么它就有構(gòu)造實(shí)例的能力瑰排,并且constructor中放的是每個(gè)通過該類構(gòu)造出來的實(shí)例都可以獲得屬性,在constructor外面放的是可以獲得的方法暖侨。
??除了在寫法上的區(qū)別椭住,class和構(gòu)造函數(shù)還有一個(gè)區(qū)別就是在class中定義的方法是不可枚舉的,而在es5中原型上添加的方法是可枚舉的字逗。還有一點(diǎn)就是京郑,使用class,在創(chuàng)建實(shí)例的時(shí)候必須使用new扳肛,而普通的構(gòu)造函數(shù)是可以省略的傻挂。
class基本語法
constructor函數(shù)
constructor是類的默認(rèn)方法,如果在寫class時(shí)挖息,沒有添加該方法金拒,js引擎會默認(rèn)添加這個(gè)方法。通過new去構(gòu)造實(shí)例時(shí)套腹,會自動去調(diào)用該方法绪抛,該方法默認(rèn)返回的是該實(shí)例對象,但是也可以指定返回的對象电禀,比如下面的情況:
class Fun {
constructor () {
// 改變默認(rèn)返回的內(nèi)容
return Object.create(null)
}
}
let fun = new Fun()
// fun不是Fun的實(shí)例
fun instanceof Fun // false
靜態(tài)屬性
如果在類中一個(gè)屬性的前面有static關(guān)鍵詞時(shí)幢码,就表明這個(gè)屬性是靜態(tài)屬性。靜態(tài)屬性是類的屬性尖飞,通過類構(gòu)造的實(shí)例中是沒有這個(gè)屬性的症副,只有通過類才可以拿到這個(gè)屬性。
靜態(tài)方法
如果在類中一個(gè)方法的前面有static關(guān)鍵詞時(shí)政基,就表明這個(gè)方法就是靜態(tài)方法贞铣。靜態(tài)方法的特殊性有兩點(diǎn):首先,在由該類創(chuàng)建的實(shí)例中沮明,是不能調(diào)用該方法的辕坝,這個(gè)方法只能通過類本身去調(diào)用;其次荐健,如果在該方法中包含this酱畅,那么this指向的是該類,下面的例子可以證明這兩點(diǎn):
class Person {
constructor (name, age) {
this.name = name
this.age = age
}
getName () {
return this.name
}
static age = 42
static getAge () {
return this.age
}
}
let huhaha = new Person ('huhaha', 21)
huhaha.getName() // huhaha
huhaha.getAge() // TypeError: huhaha.getAge is not a function
Person.getAge() // 42
class的繼承
我們知道在es5中繼承的方式有很多種江场,最簡單的方式就是通過原型鏈進(jìn)行繼承纺酸,但是就算是這種最簡單的方式也會讓人很容易混亂;為了解決這個(gè)問題址否,es6中使用extends關(guān)鍵字去表示繼承吁峻,并在子類中使用super關(guān)鍵字去繼承父類的內(nèi)容,下面這個(gè)例子可以很好的表明es6中的繼承關(guān)系:
// Father為父類
class Father {
constructor (x, y) {
this.x = x
this.y = y
}
toString () {
return 'string'
}
}
// Child為子類,繼承Father
class Child extends Father {
constructor (x, y, z) {
super (x, y) // 調(diào)用Father類中的constructor(x, y)
this.z = z
}
toString () {
return super.x + super.toString() // 通過super調(diào)用Father類中定義的方法
}
}
在上面的例子中用含,我們可以看到矮慕,子類繼承父類最關(guān)鍵的地方就是,需要在子類的constructor中使用super去繼承父類啄骇,它在這里表示的是父類的構(gòu)造函數(shù)痴鳄,用來新建父類的this對象。這里完成繼承的思想是缸夹,子類是通過先在父類中創(chuàng)建一個(gè)實(shí)例痪寻,擁有了父類中定義的屬性和方法,然后子類再添加自己的屬性和方法虽惭。這個(gè)和es5中的思想不太一致的地方在于es5中是先創(chuàng)建子類的this對象橡类,然后將父類的屬性和方法添加到子類的this中。通過圖來簡單的解釋就是:
-
es6中的實(shí)現(xiàn)思路
image.png
- es5中的實(shí)現(xiàn)思路
之前我們有講到類的靜態(tài)屬性和靜態(tài)方法芽唇,當(dāng)時(shí)說的是前面使用了static關(guān)鍵字的就是指這個(gè)類上面屬性和方法顾画,實(shí)例是拿不到的。在這里我們可以看作是這個(gè)靜態(tài)的內(nèi)容匆笤,只是針對于創(chuàng)建實(shí)例研侣,對于子類的繼承是不影響的,也就是說在子類中是可以繼承到父類中的靜態(tài)屬性和方法的炮捧,甚至于我們可以在子類中對這些屬性和方法進(jìn)行覆蓋庶诡。
檢驗(yàn)父類的方法
我們可以通過Object.getPrototypeOf方法去檢測子類與父類之間的繼承關(guān)系,如下例:
// 檢測Father是否為Child的父類
Object.getPrototypeOf(Child) === Father // true
super關(guān)鍵字
super關(guān)鍵字是實(shí)現(xiàn)繼承最關(guān)鍵的內(nèi)容咆课,它有兩個(gè)身份末誓,第一個(gè)是當(dāng)作函數(shù)使用,第二個(gè)是當(dāng)作對象使用书蚪,這個(gè)點(diǎn)其實(shí)在上面的例子也有體現(xiàn)到喇澡,現(xiàn)在我們再來仔細(xì)說一說。
作為函數(shù)使用
當(dāng)作為函數(shù)使用時(shí)善炫,super表示的是父類的構(gòu)造函數(shù),我們需要注意以下幾點(diǎn):
- 在子類中必須包含super
- 子類中的super只能在構(gòu)造函數(shù)中使用
- super內(nèi)部的this是指向子類的库继,這一點(diǎn)可以看這里
作為對象使用
當(dāng)作為對象去使用的時(shí)候箩艺,一般就是通過super去調(diào)用父類的屬性和方法了,但是這里需要注意的是宪萄,使用super只能獲取到父類原型中包含的屬性和方法艺谆,也就是說后面通過實(shí)例添加的屬性和方法是獲取不到的。我們需要注意以下幾點(diǎn):
- 在靜態(tài)方法中使用時(shí)拜英,super指向的是父類而不是父類的原型對象
- 在普通方法中使用時(shí)静汤,super指向的是父類的原型對象而不是父類本身
- 在靜態(tài)方法中通過super去調(diào)用父類的方法時(shí),this指向的是子類,而不是子類的實(shí)例
- 在使用super時(shí)虫给,我們必須顯式地表明作為對象使用還是作為函數(shù)使用