ES6中的類和對象、繼承


1.1 對象

在 Javascript 中,對象是一組無序的相關屬性和方法的集合,所有的事物都是對象,例如字符串、數值、數組、函數等。

對象是由屬性和方法組成的:

屬性:事物的特征,在對象中用屬性來表示(常用名詞)

方法:事物的行為,在對象中用方法來表示(常用動詞)

1.2 類 class

類抽象了對象的公共部分,它泛指某一大類(class)

對象特指某一個,通過實例化一個具體的對象

面向對象的思維特點:

1、抽取(抽象)對象共用的屬性和行為組織(封裝)成一個類(模板)

2、對類進行實例化,獲取類的對象

1.3 創建類

語法:

class name {
    // class body
}

創建實例:

var xx = new name();

注意:類必須使用 new 實例化對象

1.4 類 constructor 構造函數

constructor() 方法是類的構造函數(默認方法),用於傳遞參數,返回實例對象,通過 new 命令生成對象實例時,自動調用該方法。如果沒有顯示定義,類內部會自動創建一個 constructor()

注意:

1、通過 class 關鍵字創建類,類名習慣性定義首字母大寫

2、類里面有個 constructor 構造函數,可以接收傳遞過來的參數,同時返回實例對象

3、constructor 函數只要 new 生成實例時,就會自動調用這個函數,如果不寫這個函數,類也會自動生成這個函數

4、生成實例 new 不能省略

5、語法規范:創建類 類名后面沒有小括號,生成實例 類名后面加小括號,構造函數不需要加 function

1.5 類添加方法

語法:

class Person {
    constructor(name, age) {
        this.name = name;
        this.age = age
    }
    say() {
        console.log('hello, ' + this.name)
    }
}

2.1 繼承

現實中的繼承:子承父業,比如我們都繼承了父親的姓。

程序中的繼承:子類可以繼承父類的一些屬性和方法。

ES6 之前沒有提供 extends 繼承,我們可以通過 構造函數 + 原型對象 模擬實現繼承,被稱為組合繼承。示例:

function Father(name, age) {
    this.name = name;
    this.age = age
}
Father.prototype.say = function() {
    console.log('I have lots of experience.')
}

類的繼承語法:

class Father{ // 父類
}
class Son extends Father { // 子類繼承父類
}

  繼承中,如果實例化子類輸出一個方法,先看子類有沒有這個方法,如果有就先執行子類的,如果子類里面沒有,就去查找父類有沒有這個方法,如果有就執行父類的這個方法(就近原則

  實例:

class Father {
    say() {
        return 'this is father'
    }
}
class Son extends Father { // 這樣子類就繼承了父類的屬性和方法
    say() {
        return 'this is son'
        // return super.say(); //super調用父類的方法,則輸出'this is father'
    }
}
let son = new Son();
son.say(); // 'this is son'

2.2 super 關鍵字

super 關鍵字用於訪問和調用對象父類上的函數。可以調用父類的構造函數,也可以調用父類的普通函數。

class Father {
    constructor(x, y){
        this.x = x;
        this.y = y;
    }
    sum(){
        console.log(this.x + this.y)
    }
}
class Son extends Father { 
    constructor(x, y) {
        super(x, y); // 調用了父類中的構造函數constructor
        this.z = z; //定義子類獨有的屬性
    }
}
​
let son = new Son(1, 2); // 實例化了子類
son.sum();

注意: 子類在構造函數中使用super, 必須放到 this 前面 (必須先調用父類的構造方法,再使用子類構造方法),否則新建實例時會報錯(this is not defined)

因為子類沒有自己的this對象,而是繼承父類的this對象。如果不調用super方法,子類就得不到this對象。

 

注意:

1、在 ES6 中沒有變量提升,所以必須先定義類,才能通過類實例化對象

2、類里面的共有屬性和方法一定要加 this 使用

3、類里面的 this 指向問題

4、constructor 里面的 this 指向實例對象,方法里面的 this 指向這個方法的調用者

let that;
let _that;
class Star {
    constructor(uname, age) {
        console.log(this); // this 指向創建的實例對象 Star{}
        that = this;
        
        this.uname = uname;
        this.age = age;
    }
    sing() {
        // 這個里面的 this 指向的是實例對象 ldh, 因為ldh調用了這個函數
        _that = this;
        console.log(_that); //實例對象,ldh
    }
}
var ldh = new Star('劉德華');
console.log(that === ldh);  //true
ldh.sing();
console.log(_that === ldh);  //true

2.3 call()

  call() 方法調用一個對象。簡單理解即調用這個函數, 並且修改函數運行時的 this 指向。

fun.call(thisArg, arg1, arg2, ...)
  • thisArg:當前調用函數 this 的指向對象

  • arg1, arg2:傳遞的其他參數

  • 返回值就是函數的返回值,因為它就是調用函數

  • 因此當我們想改變 this 指向,同時想調用這個函數的時候,可以使用 call,比如繼承

2.4 借用構造函數繼承父類型屬性

核心原理:通過 call() 把父類型的 this 指向子類型的 this,這樣就可以實現子類型繼承父類型的屬性。

function Father(name, age) {
    this.name = name;
    this.age = age;
}
function Son(name, age) {
    // this 指向Son構造函數的實例對象
    Father.call(this, name, age)
}
const son = new Son('劉德華', 18);
console.log(son);

2.5 借用原型對象繼承父類型方法

一般情況下,對象的方法都在構造函數的原型對象中設置,那么通過構造函數創建的對象就會繼承原型的屬性和方法。

核心原理:

① 將子類所共享的方法提取出來,讓子類的 prototype 原型對象 = new 父類()

② 本質:子類原型對象等於是實例化父類,因為父類實例化之后另外開辟空間,就不會影響原來父類原型對象

③ 將子類的 constructor 重新指向子類的構造函數

function Father(name, age) {
    this.name = name;
    this.age = age;
}
Father.prototype.money = function() {
    console.log('father money');
}
function Son(name, age) {
    // this 指向Son構造函數的實例對象
    Father.call(this, name, age)
}
// Son.prototype = Father.prototype; 這樣直接賦值,如果修改了子原型對象,父原型對象也會跟着一起變化  即 console.log(Father.prototype) 也會有 exam 方法

Son.prototype = new Father(); // 此時 son的原型對象指向Father, 即console.log(Son.prototype.constructor); 指向 Father, 所以需要利用 constructor 指回原來的構造函數
Son.prototype.constructor = Son;

Son.prototype.exam = function() {
    console.log('son exam');
}
const son = new Son('劉德華', 18);
console.log(son);
console.log(Father.prototype);
console.log(Son.prototype.constructor);

圖解:

2.6 類的本質

  1. class 本質還是 function;

  1. 類的所有方法都定義在類的 prototype 屬性上;

  1. 類創建的實例,里面也有 __proto__ 指向類的 prototype 原型對象;

  2. 所以 ES6 的類它的絕大部分功能,ES5都可以做到,新的 class 寫法只是讓對象原型的寫法更加清晰、更像面向對象編程的語法而已;

  3. 所以 ES6 的類其實就是語法糖;

  1. 語法糖:語法糖就是一種便捷寫法。簡單理解,有兩種方法可以實現同樣的功能,但是一種寫法更加清晰、方便,那么這個方法就是語法糖。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM