ES6中的class

ES6發(fā)布以來,給前端開發(fā)人員帶了不少的驚喜,它包含了一些很贊的特性,極大的方便了開發(fā),class便是其中之一。在我的工作中,也用到了ES6這一新特性,雖然一直在使用,但是并沒有去認(rèn)真了解過它,于是做了一些功課,在這里跟大家分享自己的一些心得和看法。
在ES6以前,JS作為一門非面向?qū)ο蟮恼Z(yǔ)言,并沒有給我們提供對(duì)類的支持,JS開發(fā)者傳統(tǒng)的常用做法是用構(gòu)造函數(shù)來模擬類的實(shí)現(xiàn),通過將屬性和方法定義在原型上將自身的屬性共享給它的實(shí)例。
一個(gè)用構(gòu)造函數(shù)實(shí)現(xiàn)類的例子:

function Dog(name) {  
    this.name = name;  
}  
Dog.prototype.saySomething = function() {  
    console.log('汪汪汪');
};  
var dog = new Dog('LiLy'); 
dog.name //LiLy
dog.saySomething //汪汪汪

1.class的定義

而ES6引入了class,這個(gè)在面向?qū)ο笳Z(yǔ)言中常見的關(guān)鍵字,和上面的傳統(tǒng)方法相比有什么不同?這里我先用class的寫法將上面的例子改寫一下:

class Dog{
    constructor(name){
       this.name = name;            
    }
    saySomething(){
       console.log('汪汪汪');      
    }
}
var dog = new Dog('LiLy'); //也是通過new實(shí)例化
dog.name //LiLy
dog.saySomething() //汪汪汪

上面的代碼用class關(guān)鍵字定義了一個(gè)類,這個(gè)類有一個(gè)構(gòu)造函數(shù)constructor,當(dāng)通過new實(shí)例化一個(gè)對(duì)象時(shí)會(huì)自動(dòng)調(diào)用。還定義了一個(gè)saySomething方法,該方法不需要添加function也不需要prototype關(guān)鍵字。
我們已經(jīng)知道,第一種方法中通過構(gòu)造函數(shù)創(chuàng)建的類,本質(zhì)是一個(gè)函數(shù),實(shí)際是將方法添加到了函數(shù)的原型上,那通過class定義的類又如何呢,于是我試著做了以下輸出:

typeof Dog // "function" 
Dog.prototype.saySomething(); //汪汪汪
Dog.prototype.constructor === Dog //ture

這就表明,class其實(shí)跟構(gòu)造函數(shù)的實(shí)現(xiàn)沒有什么本質(zhì)的差別,類本身也是一個(gè)函數(shù),類的所有方法也是定義在prototype上,類本身指向它的構(gòu)造函數(shù),class的實(shí)現(xiàn)還是基于prototype的,它只是把prototype藏起來了
不少人管這種寫法叫做ES6的語(yǔ)法糖,因?yàn)閏lass的本質(zhì)還是ES5的語(yǔ)法,但是更加的簡(jiǎn)潔易懂、更加接近面向?qū)ο蟮膶懛ā?/p>

2.class中的屬性和方法

與面向?qū)ο笳Z(yǔ)言中類不同的是,ES6的class中只有實(shí)例屬性,無法定義類成員屬性,只能定義方法。

實(shí)例屬性######

在ES6中,類的實(shí)例屬性只能定義在構(gòu)造函數(shù)中,用this關(guān)鍵字定義只屬于實(shí)例對(duì)象本身的屬性,實(shí)例之間互不影響。千萬不要在類中直接定義成員屬性,至少目前來說是不支持的。

class Dog{
    name = 'LiLy'; //錯(cuò)誤用法,但ES7已有草案,未來可能支持這種寫法
    constructor(name){
       this.name = name; //正確         
    }

說到class中的屬性就不得不提面向?qū)ο笳Z(yǔ)言中類的屬性,通常來說,類的屬性是可以被實(shí)例繼承的,而在class中,如果我們想定義一個(gè)實(shí)例之間共享的屬性,那就只能用搬出我們的.prototype把屬性定義到類的原型對(duì)象上。

Dog.prototype.kind = 'animal'

這么看來class真是有點(diǎn)雞肋啊,還是有很多事做不了,要用到prototype才能解決問題。

原型方法與靜態(tài)方法######

原型方法能夠被類的實(shí)例繼承,實(shí)例擁有類的一切原型方法。下面的例子中,可以直接訪問通過實(shí)例調(diào)用方法saySomething()。
靜態(tài)方法在函數(shù)名稱前添加static關(guān)鍵字,這一類方法不能被實(shí)例直接調(diào)用,只能通過類名稱訪問。各位可以參照如下的例子理解一下:

class Dog{
    constructor(name){
       this.name = name;            
    }
    saySomething(){
       console.log('汪汪汪');      
    }
    static sayHello(){
      console.log('hello'); 
    }
}
var dog = new Dog('LiLy');
dog.saySomething(); //汪汪汪
Dog.sayHello(); //hello
dog.sayHello(); //dog.sayHello is not a function

3.繼承更加方便

ES6中可以用extend很方便的實(shí)現(xiàn)class之間的繼承,相比ES5中的繼承讓人愉悅得多。

class Corgi extends Dog{
    constructor(name,age){
       super(name); 
       this.name = 'Tom';
       this.age = age;         
    }
}
var corgi = new Corgi('corgi',2);
corgi.name //Tom
corgi.age // 2,不調(diào)super()則會(huì)因?yàn)檎也坏絫his對(duì)象無法初始化age的值
corgi.saySomething() //汪汪汪

在這一段代碼中,Corgi類繼承了Dog類,它能夠改寫實(shí)例屬性還能調(diào)用父類的方法。
需要注意的是,子類的構(gòu)造函數(shù)中,用了super方法調(diào)用父類的構(gòu)造函數(shù)并繼承this對(duì)象,再在自己的構(gòu)造函數(shù)中對(duì)this對(duì)象增加屬性和方法。子類不能自己生成this,而super最關(guān)鍵的作用就是生成this對(duì)象。

4.項(xiàng)目應(yīng)用

在我們金融壹賬通前端H5的項(xiàng)目中,將class作為組織頁(yè)面js的一種方式,通常來說,一個(gè)js中包含一個(gè)類的聲明和實(shí)例化。一個(gè)常見的index.js的結(jié)構(gòu)看起來會(huì)是這樣子的:

class Index {
    constructor() {
        this._init();//初始化
        this.onBack();//監(jiān)聽回調(diào)
        this.bindEvent();//事件綁定
        //更多代碼
    }
    _init(){
    //代碼塊
    }
    onBack(){
    //代碼塊
    }
    bindEvent(){
    //代碼塊
    }
new Index();

這樣組織JS最大的好處便是結(jié)構(gòu)清晰、可讀性強(qiáng)。在構(gòu)造函數(shù)中,調(diào)用了類中的幾個(gè)方法,這樣一來,我們new一個(gè)Index類的時(shí)候,會(huì)自動(dòng)運(yùn)行constructor這個(gè)函數(shù),并在里面進(jìn)行初始化、綁定事件和設(shè)置監(jiān)聽等等。
但是也看到有的同事在constructor函數(shù)中設(shè)置埋點(diǎn)、請(qǐng)求接口、初始化變量等等,這種用法雖說沒有什么錯(cuò)誤,但是違背了我們使用class的初衷,在代碼結(jié)構(gòu)上,顯得雜亂無章,不利于閱讀理解。

5.總結(jié)

缺點(diǎn):在JS中,類是基于原型繼承實(shí)現(xiàn)的,與面向?qū)ο蟮墓δ懿顒e很大,很多功能在這里都是不支持的,比如類屬性、類嵌套、多重繼承等等。兩者可以說完全不是一個(gè)東西,沒有什么可比性。
優(yōu)勢(shì):語(yǔ)法更加地簡(jiǎn)潔,不再需要每次都引用prototype去定義類的方法,也方便了編輯器檢查代碼語(yǔ)法。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • class的基本用法 概述 JavaScript語(yǔ)言的傳統(tǒng)方法是通過構(gòu)造函數(shù),定義并生成新對(duì)象。下面是一個(gè)例子: ...
    呼呼哥閱讀 4,194評(píng)論 3 11
  • JS語(yǔ)法中起始是原生不怎么支持面向?qū)ο蟮?,所有的面向?qū)ο笃鹪淳ㄟ^一個(gè)構(gòu)造函數(shù),這一點(diǎn)和JAVA等語(yǔ)言原生支持面向...
    gtt21閱讀 455評(píng)論 0 0
  • JS是一種基于對(duì)象的語(yǔ)言,要實(shí)現(xiàn)面向?qū)ο?,寫法跟傳統(tǒng)的面向?qū)ο笥泻艽蟮牟町悺S6引入了Class語(yǔ)法糖,使得JS...
    開始懂了_317閱讀 6,924評(píng)論 0 4
  • ES6中的class 簡(jiǎn)介 JS語(yǔ)法中起始是原生不怎么支持面向?qū)ο蟮?,所有的面向?qū)ο笃鹪淳ㄟ^一個(gè)構(gòu)造函數(shù),這一點(diǎn)...
    人失格閱讀 658評(píng)論 0 3
  • 1 樂高 昨天閨女發(fā)燒 就想著別踐行了 早點(diǎn)休息 誰(shuí)知閨女自己要求玩兒樂高 我問 需要圖紙嗎 閨女說需要 然后找出...
    瑩瑩生輝閱讀 153評(píng)論 0 0

友情鏈接更多精彩內(nèi)容