全面理解JavaScript中class的實現原理

1、class類概念與語法
ES5以前不存在類的概念,建立對象使用的構造函數,經過new操做符來建立;
爲使JS更像面向對象,ES6版本引入class概念,其基本語法:函數

class Cat{
    constructor(name,age){
        this.name = name;
        this.age = age;
    }
    Say(){
        return '個人名字是' + this.name;
    }
}
var cat1 = new Cat('有魚',2);
console.log(cat1.Say());//個人名字是有魚

代碼解析:
① constructor是一個構造函數方法,建立對象時自動調用該方法
② constructor是默認存在的,能夠省略,程序亦能夠調用
③ this指的是實例化對象
④類中聲明的方法不能加function關鍵字
⑤方法之間不要用逗號分隔,不然會報錯this

2、class類與原型的關係prototype

class類本質上就是一個函數,自身指向的就是構造函數,看代碼:code

console.log(typeof Cat);// function
console.log(Cat.prototype.constructor ===Cat);//true

class類是構造函數的另外一種寫法,仍然存在prototype方法對象

console.log(Cat.prototype);//object

能夠經過原型prototype修改類方法和新增方法繼承

Cat.prototype.Say = function(){
    return return '個人名字是' + this.name+',我是原型prototype聲明一樣的Say方法,把原有Say方法覆蓋了';
}
cat2 = new Cat('年年',5);
console.log(cat2.Say());//個人名字是年年,我是原型prototype聲明一樣的Say方法,把原有Say方法覆蓋了

Cat.prototype.Go = function(){
    return return '個人年齡是' + this.age;
}
console.log(cat2.Go());//個人年齡是5

還能夠經過Object.assign方法來爲對象動態增長方法get

Object.assign(Cat.prototype,{
    Eat:function(){
        return this.name;
    },
    Run:function(){
        return this.age;
    }
})
cat3 =new Cat('卡卡',4);
console.log(cat3.Eat());//卡卡
console.log(cat3.Run());//4

也可使用實例對象的__proto__屬性新增類的方法原型

cat3 =new Cat('卡卡',4);
cat4 =new Cat('樓樓',10);
cat3.__proto__.Play = function(){
    return this.name;
}
console.log(cat3.Play());// 卡卡
console.log(cat4.Play());// 樓樓

3、實例屬性和原型屬性
實例屬性:constructor裏面的屬性爲實例屬性,即定義在this對象上
原型屬性:除去實例屬性都稱爲原型屬性,即定義在class類上
hasOwnProperty方法:能夠經過hasOwnProperty()方法進行判斷屬性是不是實例屬性
in操做符:可以訪問到屬性時返回true,不管是實例屬性仍是原型屬性io

class Person(){
    constructor(per1,per2){
        this.per1 = per1;
        this.per2 = per2;
    }
    Say(){
        return per1+per2;
    }
}
var box=new Person('年年','有魚');
console.log(Person.hasOwnProperty("per1"));//true
console.log(Person.hasOwnProperty("per2"));//true
console.log(Person.hasOwnProperty("Say"));//false
console.log("per1" in Person);//true
console.log("per2" in Person);//true
console.log("Say" in Person);//true
console.log("Go" in Person);//false

4、class類的繼承console

經過extends關鍵字實現類的繼承

class Person{
    constructor(name,age){
        this.name = name;
        this.age = age;
    }
    getName(){
        return this.name;
    }
    getAge(){
        return this.age; 
    }
}
class Student extends Person{
    getName(){
        return '我覆蓋了父級的方法,'+ this.name;
    }
    getScore(){
        return '我是子級新增的方法,'+this.name;
    }
}
var stu1 = new Student('有魚',2);
console.log(sut1.getName());// 我覆蓋了父級的方法,有魚
console.log(sut1.getAge());//2
console.log(sut1.getScore());// 我是子級新增的方法,有魚

經過super關鍵字進行拓展父類構造器或方法
super做用:
①子類使用構造器constructor的時候,必須使用super關鍵字,用來擴展構造器
②子類同名方法會覆蓋父類同名方法,使用super關鍵字後則能夠調用到父類的同名函數

class Person{
    constructor(name){
        this.name = name;
    }
    getName(){
        console.log('我是父級類getName方法輸出來的');
    }
    getAge(){
        console.log(this.age); 
    }
}
class Student extends Person{
    constructor(name,age,sex){
        super();//必須先調用super,才能使用constructor,才能使用this對象
        this.name = name;
        this.age = age;
        this.sex = sex;
    }
    getName(){
        super.getName();//調用super,才能調用父類同名函數getName
        console.log('我是子級類getName方法輸出來的');
    }
}
var stu1 = new Student('有魚',2);
stu1.getName();
// 我是父級類getName方法輸出來的
// 我是子級類getName方法輸出來的

static關鍵字的使用
①static關鍵字是類的方法
②只能經過類名來調用,不能被實例對象調用
③static方法也能夠被繼承

class Person{
    constructor(name,age){
        this.name = name;
        this.age = age;
    }
    static getAge(){
        console.log('我是靜態屬性static');
    }
}
class Student extends Person{}
var stu1 = new Student('有魚',2);
Person.getAge();//我是靜態屬性static
Student.getAge();//我是靜態屬性static
stu1.getAge();//stu1.getAge is not a function
相關文章
相關標籤/搜索