大家好,我是若川。最近組織了源碼共讀活動,感興趣的可以加我微信?ruochuan12?參與。
前言
在ES5
中是原型函數,到了ES6
中出現了"類"的概念。等同于是ES5
的語法糖,大大提升了編寫代碼的速度,本文只講一些常用的(其實也就那幾個屬性),下面就讓我們來認識一下類
吧
基本使用
定義類
的關鍵字就是class
,下面這樣就是定義了一個類
,跟我們ES5
構造函數一樣,都是使用new
關鍵字
class?Person?{}const?cateory?=?new?Person()?//?調用?類
類繼承
在ES5
中,我們要繼承的話得使用call
或者prototype
來繼承原型或者實例上的方法,但是在ES6
中為我們提供了extends
關鍵字直接使用就好,同樣它會繼承方法
和屬性
class?Person?{name?=?"前端娛樂圈";hello()?{return?"你好"}
}class?Scholl?extends?Person?{getName()?{return?this.name;}
}const?res?=?new?Scholl();
console.log(res.getName())?//?前端娛樂圈
console.log(res.hello())?//?你好
constructor
constructor
構造函數,它就是當前實例的構造函數。每一個類里面只能存在一個constructor
,當類
實例化的時候(也就是new)constructor
會立即執行。如果一個類
里面沒有顯示定義constructor
構造函數的話,會默認隱式被添加進類
中并且返回值是當前類
,當然也可以顯示手動return
返回其它引用值,這時當前的實例就是constructor
的返回值。
//?默認不寫
class?Person?{
}
console.log(new?Person())?//?默認constructor指向自己的實例//?顯示寫上constructor
class?Person1?{constructor()?{}
}
console.log(new?Person1())?//?顯示地寫上constructor構造函數。實例對象返回當前的constructor//?顯示的返回對象
class?Person2?{constructor()?{return?{}}
}
console.log(new?Person2())?//?這實例的返回值就是一個空對象,constructor返回值只有是對象才可以
super關鍵字
class?Person?{}class?school?extends?Person?{constructor()?{super()?//?這里繼承了Person類,但是必須使用super調用,否則會報錯。}
}
上面school
類繼承了Person
類,如果不在constructor
中調用super
關鍵字那么它就會報錯。因為子類沒有自己的this
對象,而是繼承父類的this
對象,這里的super
關鍵字就是父類Person
對象。最終實例化返回的是school
實例,super
函數 內部會Person.prorotype.constructor.call(this)
注意,super函數只能在類中執行一次,否則會報錯
super關鍵字也可以當做一個對象使用
class?Person?{getName()?{return?"前端娛樂圈"}
}
Person.prototype.name?=?"蛙人"
Perosn.prototype.age?=?18class?school?extends?Person?{constructor()?{const?res?=?super()?//?這里的super指向Person類console.log(super.getName(),?super.name)?//?這里的super關鍵字指向Person.prototype}getAge()?{console.log(super.age)}
}
上面代碼中,super
函數只能擁有一個,但super
關鍵字可以當成一個對象使用,super
關鍵字當成對象指向的是父類prototype
原型對象。super
關鍵字可以在類的任何地方使用,但super
函數只能在constructor
中使用。
注意:super函數返回值是當前類的實例,super關鍵字指向的當前類的prototype
get
用于獲取取值屬性,剛在上面我們說過,私有屬性不能在類的外部訪問,但是我們可以通過get
關鍵字來獲取類里面的私有屬性。
class?Person?{private?username?=?"前端娛樂圈";private?age?=?18;get?getVal()?{return?this.username;}
}
const?res?=?new?Person();?
console.log(res.getVal)?//?前端娛樂圈
那么我們來看一下,這個get
關鍵字和定義一個方法有何不同。
class?Person?{private?username?=?"前端娛樂圈";private?age?=?18;getVal()?{return?this.username;}
}
const?res?=?new?Person();?
console.log(res.getVal())?//?前端娛樂圈
上面我們把get
關鍵字去掉了,并且調用時候的帶上了()
代表要執行一個函數。雖然這樣寫跟get
關鍵字效果是一樣的,但是不推薦我們這么寫,就像Vue
中我們使用computed
寫,就不推薦methods
里面寫。官方定義的get
是取值函數,我們取值直接用get
關鍵字就行也不用寫()
,就像獲取一個屬性一樣。
set
set
存值函數,上面說了get
,那么有get
就一定有set
。存值函數跟取值函數一個意思,一個獲取一個設置嘛。
class?Person?{private?username?=?"前端娛樂圈";private?age?=?18;get?getVal()?{return?this.username;}set?setVal(val)?{this.username?=?val}
}
const?res?=?new?Person();?
res.setVal?=?"蛙人"
console.log(res.getVal())?//?蛙人
上面我們先執行了存值,然后在取值,跟我們預期的結果一樣,我們存值改變了username
,獲取值也會改變。
私有屬性
在類中私有屬性必須以#
開頭聲明,以#
開頭的只能在類中訪問,在類的外部不能訪問。如果用的TypeScript
完全可以使用private
代替。
class?Person?{#name?=?"蛙人"constructor()?{}getName()?{return?this.#name}#getAge()?{return?18}
}
const?res?=?new?Person();
//?console.log(this.#name)?//?報錯,必須在封閉類中聲明該字段
console.log(res.getName())?//?蛙人
console.log(res.#getAge)?//?報錯,getAge?is?not?function
static
static
為類
的靜態屬性,"靜態數據"是啥意思呢,就是不用實例化類
就可以訪問的屬性。像我們不是static
定義的屬性和方法都必須的實例化類才能調用。
這里需要注意一下,當我們定義完
非static定義的屬性
class?Person?{username?=?"前端娛樂圈";age?=?18;
}
const?res?=?new?Person().username;?//?前端娛樂圈
像我們這種非static
定義的屬性,要想訪問username
屬性就必須得實例化new
才能訪問。
static定義的屬性
static
定義的靜態屬性,就是不用實例化就可以直接訪問。不定義在實例化對象上面。
//?之前老的寫法
class?Person?{}
Person.username?=?"前端娛樂圈"//?新寫法,加一個static關鍵字即可
class?Person?{static?username?=?"前端娛樂圈";static?age?=?18;static?getName()?{return?Person.username}
}console.log(Person123.username,?Person123.getName())?//?前端娛樂圈,前端娛樂圈
之前老寫法的靜態屬性定義在類的外部。整個類生成以后,再生成靜態屬性。這樣讓人很容易忽略這個靜態屬性,也不符合相關代碼應該放在一起的代碼組織原則。為了解決這問題,就新出的static
關鍵字靜態方法
以下這三個修飾符是在
TypeScript
類中才能使用,在JavaScript
類中是不支持的。

public
public
為類
的公共屬性,就是不管在類
的內部還是外部,都可以訪問該類
中屬性及方法。默認定義的屬性及方法都是public
。
class?Person?{name?=?"前端娛樂圈";public?age?=?18;
}
const?res?=?new?Person();
console.log(res.name,?res.age)?//?前端娛樂圈?18
上面可以看到打印結果都能顯示出來,name
屬性沒有定義public
公共屬性,所以類
里面定義的屬性及方法默認都是public
定義。
private
private
為類
的私有屬性,只有在當前類
里面才能訪問,當前類
就是{}
里面區域內。在{}
外面是不能訪問private
定義的屬性及方法的
class?Person?{private?name?=?"前端娛樂圈";private?age?=?18;
}
const?res?=?new?Person();
console.log(res.name,?res.age)?//?這倆行會爆紅,當前屬性為私有屬性,只能在類內部訪問class?Scholl?extends?Person?{getData()?{return?this.username?+?","?+?this.age}
}
const?temp?=?new?Scholl()
console.log(temp.getData())?//?爆紅~,雖然繼承了Person類,但是private定義是只能在當前類訪問,子類也不能訪問。
protected
protected
為類
的保護屬性,只有在當前類和子類可以訪問。也就是說用protected
屬性定義的子類也可以訪問。
class?Person?{protected?username?=?"前端娛樂圈";protected?age?=?18;
}
const?res?=?new?Person();
console.log(res.name,?res.age)?//?這倆行會爆紅,當前屬性為私有屬性,只能在類內部訪問class?Scholl?extends?Person?{getData()?{return?this.username?+?","?+?this.age}
}
const?temp?=?new?Scholl()
console.log(temp.getData())?//?前端娛樂圈,18。可以正常訪問父類的屬性
例子
例如我們寫如下一個小Demo
彈窗,可以單獨寫一個class類
里面,這樣寫法是不是比我們ES5
中的prototype
寫法看著舒服多了。當然我們日常開發中的業務,公共方法也可以寫進一個類
里面
class?Mask?{isShow?=?false;elem?=?nullconstructor()?{this.elem?=?this.init()}init()?{const?oDiv?=?document.createElement("div");document.body.appendChild(oDiv);return?oDiv;}show()?{this.elem.style.display?=?"block"this.isShow?=?true;}hide()?{this.elem.style.display?=?"none"this.isShow?=?false;}
}
結語
ES6
的class類
畢竟是一個“語法糖”,所以只要理解了JavaScript
中對象的概念和面向對象的思想,class
?就不難理解啦~,下篇準備更新TypeScript文章
感興趣的小伙伴可以點個關注+贊哦。
最近組建了一個江西人的前端交流群,如果你是江西人可以加我微信?ruochuan12?私信 江西 拉你進群。
推薦閱讀
1個月,200+人,一起讀了4周源碼
我歷時3年才寫了10余篇源碼文章,但收獲了100w+閱讀
老姚淺談:怎么學JavaScript?
我在阿里招前端,該怎么幫你(可進面試群)
·················?若川簡介?·················
你好,我是若川,畢業于江西高校。現在是一名前端開發“工程師”。寫有《學習源碼整體架構系列》10余篇,在知乎、掘金收獲超百萬閱讀。
從2014年起,每年都會寫一篇年度總結,已經寫了7篇,點擊查看年度總結。
同時,最近組織了源碼共讀活動,幫助1000+前端人學會看源碼。公眾號愿景:幫助5年內前端人走向前列。
識別上方二維碼加我微信、拉你進源碼共讀群
今日話題
略。歡迎分享、收藏、點贊、在看我的公眾號文章~