ECMAScript 是一個包含多種 Paradigm 的程式語言,當使用 this
時,基本上就是以 OOP 風格開發,以 this
指向 Object。目前 ECMAScript 有 Object Literal、Constructor Function 與 Class 三種方式實現 OOP,將分別討論之。
Version
ECMAScript 2020
Object Literal
let getName = function() {
return this.name
}
let john = {
name: 'John',
getName
}
let sam = {
name: 'Sam',
getName
}
john.getName() // ?
sam.getName() // ?
Object Literal 會直接以 Object 實現 OOP。
第 5 行
let john = {
name: 'John',
getName
}
let sam = {
name: 'Sam',
getName
}
直接定義 john
與 sam
兩個 Object,其中 name
property 有各自不同資料,但 getName()
是相同的。
第 1 行
let getName = function() {
return this.name
}
因為 method 都相同,可單獨提出 getName()
,並以 this
存取 property,此時 this
掛在哪一個 Object,則 this
就指向該 Object,如此就不必在每個 Object 都佔記憶體存放 method,getName()
可共用同一份記憶體。
可發現 ECMAScript 因為使用
this
讀取 property,因此同一個 function 可套用在多個 Object,可藉此節省記憶體使用
Constructor Function
let John = function() {
this.name = 'John'
}
let Sam = function() {
this.name = 'Sam'
}
let getName = function() {
return this.name
}
John.prototype.getName = getName
Sam.prototype.getName = getName
let john = new John
john.getName() // ?
let sam = new Sam
sam.getName() // ?
也可以使用 constructor function 實現 OOP。
第 1 行
let John = function() {
this.name = 'John'
}
let Sam = function() {
this.name = 'Sam'
}
使用 constructor function 建立 property。
第 9 行
let getName = function() {
return this.name
}
John.prototype.getName = getName
Sam.prototype.getName = getName
使用 prototype
建立 method,因為 getName()
都相同,也可將 getName()
提出,如此 John
與 Sam
都共用同一份 getName()
節省記憶體,且均以 this
存取 property,此時 this
指向 new
所建立的 Object。
16 行
let john = new John
john.getName() // ?
let sam = new Sam
sam.getName() // ?
以 new
對 constructor function 建立 Object。
Class
class Student {
constructor(name) {
this.name = name
}
getName() {
return this.name
}
}
class John extends Student {
constructor() {
super('John')
}
}
class Sam extends Student {
constructor() {
super('Sam')
}
}
let john = new John
john.getName() // ?
let sam = new Sam
sam.getName() // ?
ES6 也提供以 class 實現 OOP。
第 1 行
class Student {
constructor(name) {
this.name = name
}
getName() {
return this.name
}
}
若要 John
與 Sam
class 都共用 getName()
,只能將 getName()
寫在其 parent class,一樣使用 this
存取 property,此時 this
指向 new
所建立的 Object。
11 行
class John extends Student {
constructor() {
super('John')
}
}
class Sam extends Student {
constructor() {
super('Sam')
}
}
John
與 Sam
class 都使用 extends
繼承 Student
class,因此只有一份 getName()
節省記憶體。
23 行
let john = new John
john.getName() // ?
let sam = new Sam
sam.getName() // ?
一樣使用 new
建立 Object。
Conclusion
- FP 不會使用
this
,當使用this
就是以 OOP 開發 - 可發現無論使用 object literal、constructor function 或 class,三種寫法都可以使用
this
指向 Object,但別忘了 ECMAScript 是以 function 實現 OOP,因此this
會隨 context 而變,而非如 OOP 永遠指向相同 Object