在ES5中刻像,我們經(jīng)常使用方法或者對象去模擬類的使用板甘,并基于原型實現(xiàn)繼承忽妒,雖然可以實現(xiàn)功能熄赡,但是代碼并不優(yōu)雅姜挺,很多人還是傾向于用 class 來組織代碼,很多類庫彼硫、框架創(chuàng)造了自己的 API 來實現(xiàn) class 的功能初家。
ES6 時代終于有了 class (類)語法,能讓我們可以用更簡明的語法實現(xiàn)繼承乌助,也使代碼的可讀性變得更高,同時為以后的JavaScript語言版本添加更多的面向?qū)ο筇卣鞔蛳禄A(chǔ)陌知。
一他托、 類的定義
- ES5使用函數(shù)模擬類
function Person( name , age ) {
this.name = name;
this.age = age;
}
Person.prototype.say = function(){
return '我叫' + this.name + ',今年' + this.age + '歲';
}
var p = new Person('xiaoming',33); // Person {name: "xiaoming", age: 33}
p.say();
使用ES5語法定義了一個Person類,該類有name age food三個屬性和一個原型eat方法仆葡。
2.ES class定義類
class Person{
constructor(name,age){
this.name = name;
this.age = age;
}
say(){
return '我叫' + this.name + ',今年' + this.age + '歲';
}
}
var stu = new Person("xiaoming",22);
p.say();
上面代碼定義了一個同樣的Person類赏参,constructor方法就是構(gòu)造方法,而this關(guān)鍵字則代表實例對象;
注:雖然ES6引入了class關(guān)鍵字沿盅,但并沒有真的引入類這個概念把篓,通過class定義的仍然是函數(shù),數(shù)據(jù)類型中也沒有class類型腰涧。
console.log(typeof Person);//還是'function'
所以說韧掩,class僅僅是通過更簡單直觀的語法去實現(xiàn)原型鏈繼承。這種對語言功能沒有影響窖铡、但是給程序員帶來方便的新語法疗锐,被稱為語法糖。
二费彼、類的傳參
在類的參數(shù)傳遞中,我們在constructor( )進(jìn)行傳參滑臊,傳遞參數(shù)后可以直接使用this.xxx進(jìn)行調(diào)用。
class Person{
constructor(x,y){
this.x = x;
this.y = y;
}
add(){
return this.a + this.b;
}
}
let stu = new Person(11,22);
stu.add();//11+22=33
用constructor來傳遞參數(shù)箍铲,然后用了一個add方法雇卷,把參數(shù)相加。
三、靜態(tài)方法
- 使用函數(shù)模擬類時关划,通過函數(shù)名.靜態(tài)方法名小染,來定義靜態(tài)方法:
function Person(name,age){
this.name = name;
this.age = age;
Person.say = function(){
return "I can say!"
}
}
Person.say();//I can say!
var student = new Person("xiaoming",11);
student.say();//報錯
靜態(tài)方法是不需要實例化祭玉,可以通過類名直接調(diào)用氧映,注意的是靜態(tài)方法不會繼承到類實例中,因此靜態(tài)方法經(jīng)常用來作為工具函數(shù)脱货。比如我們經(jīng)常用的Math.random()岛都。
- 在ES6 class類定義中,可以使用static關(guān)鍵字定義靜態(tài)方法:
class A{
constructor(){};
static say(){
console.log("I can say!");
}
}
A.say();//I can say
var a = new A();
a.say()//error
跟之前一樣振峻,通過類名直接調(diào)用臼疫,不會繼承到類實例中。
static關(guān)鍵字是ES6的另一個語法糖扣孟,static 使靜態(tài)方法聲明也成為了一個一等公民烫堤。
四、封裝和繼承
- ES6之前子類對象是通過使用原型來實現(xiàn)繼承父類凤价,子類函數(shù)和父類函數(shù)共享原型的形式來實現(xiàn):
function Person(name,age){
this.name = name;
this.age = age;
}
function father(name,age,firstname,lastname){
Person.call(this,name,age);//通過call來繼承父類的方法來實現(xiàn)自己的功能
this.lastname = lastname;
this.firstname = firstname;
}
console.log(new father('zhangsan',11,'zhang','san'));
//father {name: "zhangsan", age: 11, lastname: "san", firstname: "zhang"}
function son(name,age,firstname,lastname){
father.call(this,name,age,firstname,lastname);
};
son.prototype = Object.create(father.prototype);
son.constructor = son;
console.log(new son('zhangsi',5,'zhang','si'));
//son {name: "zhangsi", age: 5, lastname: "si", firstname: "zhang"}
- ES6中新的extends關(guān)鍵字解決了這個麻煩問題:
語法:class son extends father{}
下面定義了一個Child類鸽斟,該類通過extends關(guān)鍵字,繼承了Parent類的所有屬性和方法利诺。
class Parent{
constructor(firstname,lastname){
this.firstname = firstname;
this.lastname = lastname;
}
}
class Child extends Parent{
constructor (firstname,lastname,name){
super(firstname,lastname);
this.name = name;
}
say(){
console.log("I can say!")
}
}
console.log(new Child("蒙奇","D","路飛"));
//Child {firstname: "蒙奇", lastname: "D", name: "路飛"}
- super關(guān)鍵字
super表示超富蓄,超類,父類慢逾。既可以當(dāng)作函數(shù)立倍,也可以當(dāng)作對象使用。
(1)super作為函數(shù)調(diào)用侣滩,代表父類的構(gòu)造函數(shù)口注。
注意,ES6中規(guī)定君珠,子類的構(gòu)造函數(shù)必須執(zhí)行一次super函數(shù)寝志。格式:
class Parent{}
class Child extends Parent{
constructor (){
super();
// ...
}
// ...
}
class Parent{}
class Child extends Parent{
constructor (){
// super(); 如果調(diào)用super,程序會報錯Uncaught ReferenceError: this is not defined
// ...
}
// ...
}
new Child();
注意,super雖然代表父類中的構(gòu)造函數(shù)葛躏,但是返回的是子類的實例澈段,即super內(nèi)部的this指的是子類Child,在這種情況下舰攒,super()相當(dāng)于Parent.prototype.constructor.call(this)败富。
(2)super作為對象,代表父類的原型對象摩窃。
class Parent{
constructor(firstname,lastname,age){
this.firstname = firstname;
this.lastname = lastname;
this.age = age;
}
say(){
console.log("I can say.");
}
}
class Child extends Parent{
constructor (firstname,lastname,age,score){
super(firstname,lastname,age); //super在這里代表父類的構(gòu)造函數(shù)
this.score = score;
super.say();//super在這里代表父類的原型對象兽叮,可以調(diào)用父類的方法
}
}
console.log(new Child("蒙奇","路飛",18,100));
// I can say.
// {firstname: "蒙奇", lastname: "路飛", age: 18, score: 100}
使用extends關(guān)鍵字實現(xiàn)繼承芬骄,那么子類中可以通過super關(guān)鍵字調(diào)用父類的東西
(3)4.3 getter(取值)、 setter(存值)
與 ES5 一樣鹦聪,在“類”的內(nèi)部可以使用get和set账阻,對某個屬性設(shè)置存值函數(shù)和取值函數(shù),攔截該屬性的存取行為泽本。
class Parent{
constructor(){}
get firstname(){
return "D.";
}
set lastname(value){
console.log('我的名是:' + value);
}
}
let p = new Parent();
console.log(p.firstname);//D.
console.log(p.lastname = "路飛") ;
//我的名是:路飛
//路飛