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