這篇文章主要介紹了es6 class是不是語(yǔ)法糖的相關(guān)知識(shí),內(nèi)容詳細(xì)易懂,操作簡(jiǎn)單快捷,具有一定借鑒價(jià)值,相信大家閱讀完這篇es6 class是不是語(yǔ)法糖文章都會(huì)有所收獲,下面我們一起來(lái)看看吧。
惠州網(wǎng)站制作公司哪家好,找創(chuàng)新互聯(lián)!從網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站建設(shè)、微信開發(fā)、APP開發(fā)、自適應(yīng)網(wǎng)站建設(shè)等網(wǎng)站項(xiàng)目制作,到程序開發(fā),運(yùn)營(yíng)維護(hù)。創(chuàng)新互聯(lián)公司2013年成立到現(xiàn)在10年的時(shí)間,我們擁有了豐富的建站經(jīng)驗(yàn)和運(yùn)維經(jīng)驗(yàn),來(lái)保證我們的工作的順利進(jìn)行。專注于網(wǎng)站建設(shè)就選創(chuàng)新互聯(lián)。
class是語(yǔ)法糖。原因:class是基于原型繼承的實(shí)現(xiàn),對(duì)語(yǔ)言的功能并沒(méi)有什么影響,只是方便了語(yǔ)法的書寫及閱讀;class的本質(zhì)是function,能夠讓對(duì)象原型的寫法更加清晰,更像面向?qū)ο缶幊痰恼Z(yǔ)法。
本教程操作環(huán)境:windows7系統(tǒng)、ECMAScript 6版、Dell G3電腦。
ES6 class類——語(yǔ)法糖
class (類)作為對(duì)象的模板被引入,可以通過(guò) class 關(guān)鍵字定義類。它的本質(zhì)是函數(shù)(function),可以看作一個(gè)語(yǔ)法糖,讓對(duì)象原型的寫法更加清晰、更像面向?qū)ο缶幊痰恼Z(yǔ)法。
它的class和別的語(yǔ)言不一樣,它依舊是基于原型繼承的實(shí)現(xiàn),對(duì)語(yǔ)言的功能并沒(méi)有影響,只是方便了你的書寫及閱讀
為什么說(shuō)ES6的class是語(yǔ)法糖
我們帶著問(wèn)題去閱讀下文:
為什么說(shuō)ES6的class是語(yǔ)法糖?
class是原型的語(yǔ)法糖嗎?
那又是如何使用原型來(lái)實(shí)現(xiàn)class這一語(yǔ)法糖的呢?
1. 基于Prototype的OOP
先來(lái)看一個(gè)prototype的例子:
function Person (name, sex) {
this.name = name
this.sex = sex
}
function Man (name) {
this.name = name
}
Man.prototype = new Person('', 'male')
let Jy = new Man('Jy')
console.log(Jy.name, Jy.sex) // Jy, male
這是我們使用原型的一個(gè)很簡(jiǎn)單的例子,Person具有名字和性別,Man是一個(gè)性別為男的Person,Jy是一個(gè)Man。我們先記住這一個(gè)例子,下面將使用class重寫這個(gè)例子。
Tips: new, this等是Brendan Eich使之更像Java的OOP而加上的,有興趣的讀者可以自行查閱相關(guān)信息。
2. ES6 Class的OOP
class Person {
constructor (name, sex) {
this.name = name
this.sex = sex
}
}
class Man extends Person {
constructor (name) {
super('', 'male')
this.name = name
}
}
let Jy = new Man('Jy')
console.log(Jy.name, Jy.sex) // Jy, 'male'
我們通過(guò)重寫這個(gè)例子,采用了class、constructor、extends、super 這些單詞,接下來(lái)就具體來(lái)說(shuō)說(shuō)ES6規(guī)范中對(duì)它們做了什么。
3. 使用Prototype實(shí)現(xiàn)的Class OOP(ES6規(guī)范)
在ES6之前,JS對(duì)象其實(shí)就是屬性的集合,而屬性則是一組鍵值對(duì)(key, value),key可以是String or Symbol, value包括數(shù)據(jù)屬性特征值和訪問(wèn)器特征值。
你說(shuō)普通的屬性還好,不還有對(duì)象下面的方法嗎?怎么就變成了屬性的集合呢?
其實(shí)在ES5規(guī)范中出現(xiàn)的method的定義是“function that is the value of a property”,是對(duì)象的函數(shù)屬性而已,不能稱之為方法,直到ES6出現(xiàn),規(guī)范中才有Method Definitions。
我們能想到的在ES3有關(guān)OOP的東西: prototype、new、 this、 constructor、 instanceof, 甚至不是規(guī)范的 __proto__
屬性。
所幸的是在ES5中我們?cè)黾恿撕芏喾椒▉?lái)補(bǔ)全它,使之完備:
Object.defineProperty
Object.freeze
Object.create
Object.getPrototypeOf
Object.setPrototypeOf
isPrototypeOf
......
再來(lái)看一段代碼:
let obj = {
name: 'Jy',
speak () { // Note: it's not speak: function () {}
console.log(this.name, super.name)
}
}
obj.speak() // Jy, undefined
Object.setPrototypeOf(obj, { name: 'super' })
obj.speak() // Jy, super
let speak = obj.speak
speak() // undefined, super
obj.speak在ES6中定義已經(jīng)是Method了,它具有屬性[[homeObject]],homeObject指向方法被調(diào)用的對(duì)象(代碼中指的是obj), 它是綁定在對(duì)象中的Internal Slots,也就是你不能去修改,就相當(dāng)于寫死了。
那么homeObject有什么用呢?它跟super密切相關(guān),當(dāng)解析到super這一關(guān)鍵字的時(shí)候就會(huì)找homeObject的prototype。
簡(jiǎn)單來(lái)說(shuō),總結(jié)為下面兩條公式:
let homeObj = Method[[HomeObject]] = obj
super = Object.getPrototypeOf(homeObj)
Note: homeObject是靜態(tài)綁定在internal slots中的,而super是動(dòng)態(tài)查找的。
講完super,我們來(lái)講講extends和constructor
class A extends B { }
class A extends B {
constructor (...args) {
super(args)
}
}
class C extends null { }
extends主要做了以下兩件事:
Object.setPrototypeOf(A, B)
Object.setPrototypeOf(A.prototype, B.prototype)
如果父類是null, 則執(zhí)行Object.setPrototypeOf(C.prototype, null)
上述代碼的第一和第二部分區(qū)別在于有沒(méi)有顯示聲明constructor, 那么這兩段代碼是否等價(jià)呢?答案是等價(jià)的。
規(guī)范中就是這么定義的:
代碼的第三部分是繼承了null, 它不會(huì)報(bào)語(yǔ)法錯(cuò)誤,但是我們無(wú)法new一個(gè)C出來(lái),原因是new的時(shí)候會(huì)調(diào)用null的constructor,而null沒(méi)有constructor。
看到這里,ES6的class oop, 規(guī)范聲明都是使用原型來(lái)操作,所以我們是不是可以說(shuō)class是原型的語(yǔ)法糖了?
4. babel編譯后的class
我們實(shí)際項(xiàng)目中多采用babel來(lái)編譯ES6、7的代碼,所以這節(jié)我們就來(lái)分析以下babel編譯后的代碼,其中會(huì)省略一些報(bào)錯(cuò)、類型檢測(cè)的一些相關(guān)代碼來(lái)更好地呈現(xiàn)使用原型來(lái)實(shí)現(xiàn)OOP的主題。
編譯前:
class A extends B {}
console.log(new A)
編譯后:
"use strict";
function _getPrototypeOf(o) {
_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
return o.__proto__ || Object.getPrototypeOf(o);
};
return _getPrototypeOf(o);
}
function _inherits(subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function");
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
writable: true,
configurable: true
}
});
if (superClass) _setPrototypeOf(subClass, superClass);
}
function _setPrototypeOf(o, p) {
_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
o.__proto__ = p;
return o;
};
return _setPrototypeOf(o, p);
}
var A =
/*#__PURE__*/
function (_B) {
_inherits(A, _B);
function A() {
return _getPrototypeOf(A).apply(this, arguments);
}
return A;
}(B);
console.log(new A());
我們重點(diǎn)看_inherits 方法,跟我們上述說(shuō)的extends做的兩件事是一樣的:
Object.setPrototypeOf(subClass, superClass)
Object.setPrototypeOf(subClass.prototype, superClass.prototype)
只不過(guò)它采用的是Object.create方法,這兩個(gè)方法的區(qū)別可以去MDN上查看。
再看function A內(nèi)部,其實(shí)就是執(zhí)行了B的構(gòu)造器函數(shù)來(lái)達(dá)到super(arguments)的效果, 這個(gè)與規(guī)范:如果沒(méi)有顯示聲明constructor會(huì)自動(dòng)加上constructor是一致的。
關(guān)于“es6 class是不是語(yǔ)法糖”這篇文章的內(nèi)容就介紹到這里,感謝各位的閱讀!相信大家對(duì)“es6 class是不是語(yǔ)法糖”知識(shí)都有一定的了解,大家如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。