ES6語法:class類,從了解到使用

  • 2020 年 12 月 28 日
  • 筆記

前情提要

   JavaScript 語言中,在使用類之前,生成實例對象的傳統方法是通過使用構造函數。

 

一、構造函數:

      定義:通過  new 函數名  來實例化對象的函數叫構造函數。

    主要功能:為初始化對象,特點是和new 一起使用。new就是在創建對象,從無到有,構造函數就是在為初始化的對象添加屬性和方法。

    注意:任何的函數都可以作為構造函數存在構造函數定義時首字母大寫(規範)。

    對new的理解:new 申請記憶體, 創建對象,當調用new時,後台會隱式執行new Object()創建對象。所以,通過new創建的字元串、數字是引用類型,而是非值類型。

 

    1、常用的構造函數:

    • var arr = [];為 var arr = new Array()的語法糖

    • var obj = {}; 為 var obj = new Object()的語法糖

    • var date = new date()

    • 當然還有很多,這裡就不一 一列舉了。

  2、執行一個構造函數:

function A(name,age){   this.name = name;   this.age = age; }
A.prototype.info = function(){
  return “姓名”+ “” + this.name + “年齡” + this.age
}
let a = new A(“張三”,22)//實例化a
//列印 a結果
A{
  name:”張三”,
  age:22
}
//列印 a.info() 結果為 “姓名張三年齡22”

二、class 類

    由來:因為上面構造函數的寫法跟傳統的面向對象語言差異很大,給很多程式設計師造成很多困惑,所以ES6 提供了更接近傳統語言的寫法,引入了 Class(類)這個概念,作為對象的模板。

    通過class關鍵字,可以定義類。

   1、class類基本語法的使用

class A{
  constructor(){
    //成員屬性

    this.name = name
    this.age = age
  }
  //靜態方法 如果在一個方法前,加上static關鍵字,就表示該方法不會被實例繼承,而是直接通過類來調用,這就稱為「靜態方法」。A.nihao()
  static nihao(){
    console.log(“你好”)
  }
  //成員方法

  info(){
    return “姓名”+ “” + this.name + “年齡” + this.age 
  }
}

    與上面的構造函數相比之言,新的class寫法讓對象原型的寫法更加清晰、更像面向對象編程的語法。

     注意:定義info()方法的時候,前面不需要加上function這個關鍵字,直接把函數定義放進去了就可以了方法與方法之間不需要逗號分隔,加了會報錯。

     添加靜態屬性:

        靜態屬性指的是 Class 本身的屬性,即Class.propName,而不是定義在實例對象(this)上的屬性。

     老式寫法:

     class A{}

     A.props=1 //A.props= 1   props就是A的靜態屬性 

     新式寫法:

     class A{

      static props = 1

     }

    新寫法是顯式聲明(declarative),而不是賦值處理,語義更好。

 

    私有方法私有屬性

      私有方法兩種寫法:    

      function bar(name){

       return this.name = name

      }

      class A{

        foo(name){

          bar.call(this,name)

        }

        }

     這樣寫的原因是類內部的所有方法都是對外可見的。foo是公開方法,內部調用了bar.call(this, baz)。這使得bar()實際上成為了當前類的私有方法。

 

     還有一種方法是利用Symbol值的唯一性,將私有方法的名字命名為一個Symbol值。

     const bar = Symbol(‘bar’)

     const  name = Symbol(‘name’)

     class A{

      //公有方法

      foo(){

        this[bra](name)

      }

      //私有方法

      [bar](name){

          return this[name] = name

      }

 

     }

    私有屬性

    第一種方法是在屬性名之前,使用#表示。

    class A{

      #count = 0

 

    }

    注意:#count就是私有屬性,只能在類的內部使用(this.#count)。如果在類的外部使用,就會報錯。

 

      這種寫法不僅可以寫私有屬性,還可以用來寫私有方法。

    私有屬性也可以設置 getter 和 setter 方法。

class Foo {
#a;
#b;
#xVal = 0;
constructor(a, b) {
this.#a = a;
this.#b = b;
}
#sum() {
return this.#a + this.#b;
}
printSum() {
console.log(this.#sum());
}

get #x() { return #xValue; }

set #x(value) {

this.#xValue = value;

}

}
私有屬性不限於從this引用,只要是在類的內部,實例也可以引用私有屬性。
私有屬性和私有方法前面,也可以加上static關鍵字,表示這是一個靜態的私有屬性或私有方法。

 

  2、深入介紹class類和class繼承

   <1>

 

     ES6 的類,完全可以看作構造函數的另一種寫法。

              class A{}  typeof A //function  A === A.prototype.constructor // ture 可以看出,類的數據類型就是函數,類本身就指向構造函數。

    使用的時候,也是直接對類使用new命令,跟構造函數的用法完全一致。

    <2>

    class A{

      constructor(){}

      info(){}

      toString(){}

      toVal(){}

    }

    等同於

    A.prototype={

      info(){},

      toString(){},

      toVal(){},

    };

    構造函數的prototype屬性,在類裡面也存在,類的所有方法都定義在類的prototype屬性上面.

    因此,在類的實例上面調用方法,其實就是調用原型上的方法。

    <3>

    Object.assign()  方法可以很方便地一次向類添加多個方法。如下:

         Object.assign(A.prototype,{

      toString(){},

      toVal(){},

      })

    <4>

    類的內部所有定義的方法,都是不可枚舉的,如下:

class A{
constructor(x, y) {
// ...
}
toString() {
// ...
}
}
Object.keys(A.prototype)
// []
<5>

    類內部可以忽略不寫constructor,因為JavaScript 引擎會自動為它添加一個空的constructor()方法。如下:

    class A{} === class A{constructor(){}} //true

    <6>

    constructor()方法默認返回實例對象(即this),完全可以指定返回另外一個對象。

    <7>

    類必須使用new調用,否則會報錯。這是它跟普通構造函數的一個主要區別,後者不用new也可以執行。

 

三、class繼承:

<1>class 通過extends關鍵字實現繼承,這樣的繼承方式非常清晰和方便

class A{}

class B extends A{

 constructor(){

   super() //關鍵字,super作為函數調用時,代表父類的構造函數

   }

} //B類繼承了A類的所有屬性和方法

<2>Object.getPrototypeof(B)=== A //true 方法可以用來從子類上獲取父類 ,因此,可以使用這個方法判斷,一個類是否繼承了另一個類。