ES6語法:class類,從瞭解到使用
前情提要:
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 方法可以用來從子類上獲取父類 ,因此,可以使用這個方法判斷,一個類是否繼承了另一個類。