聽說你對 ES6 class 類還不是很瞭解

前言

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 = 18

class 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類中是不支持的。

報錯. png

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 = null
  constructor() {
      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;
  }
}

結語

ES6class類畢竟是一個 “語法糖”,所以只要理解了JavaScript中對象的概念和麪向對象的思想,class 就不難理解啦~,下篇準備更新TypeScript文章感興趣的小夥伴可以點個關注 + 贊哦。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/JgqCZooaNo6jfM3yHLi1EQ