[JavaScriptWeird]No.68 物件導向的基礎範例與 class

前言

這節要來研究一下如何使用 ES6 新增的 class 實作出物件導向的範例,以及尚未出現 class 時,是如何處理這部分的?

ES6 新增的 class

直接看程式碼

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class dog {  
constructor(name) {
this.name = name;
}
getName(){
return this.name;
}
sayHello() {
console.log(this.name + ' say Hello');
}
}

var d = new dog('abc');
var b = new dog('qqq');
console.log(d);
console.log(d.getName());
d.sayHello();
console.log(d.sayHello === b.sayHello); // true

ES6 新增的 class 就像是一張設計圖,沒使用建構子 new 之前是沒有辦法使用的。

以這個例子來說,我們要建立狗的類別,所以我們定義了三個函式,其中 constructor 函式比較特別,當使用建構子 new 實例化 (instance) 狗的 class 時,可在括號內放入參數,而 constructor 函式可以取得該參數。

這個例子中以這樣的方式初始化每隻狗的名字,而我們可以更進一步的觀察

  • 此時的變數 d 與變數 b 使用 typeof 觀察會是物件
  • 以此設計圖新增的每隻狗都有定義在設計圖內的函式
  • 使用三等號比較兩者的 sayHello 方法,會回傳 true ,代表為同個函式

ES5 沒有 class 的作法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function dog(name){  
this.name = name;
}

dog.prototype.getName = function(){
return this.name;
}

dog.prototype.sayHello = function(){
console.log(this.name + ' say Hello');
}

var d = new dog('abc');
var b = new dog('qqq');
console.log(d);
console.log(d.getName());
d.sayHello();
console.log(d.sayHello === b.sayHello); // true

可以發現差別並不大,直觀來說下半部的程式碼幾乎是一樣的。

主要就是需要宣告一個函式,而這個函式其實就是 ES6 class 內的 constructor 函式。

而在 ES5 的時候,是看使用時有沒有加入建構子 new 來決定是否為 constructor 函式或是一般的函式。

然後除了要宣告一個函式之外,也必須在該函式的 prototype 定義這些狗會做什麼。

接下來進行一些觀察,可以得知跟上面那個例子的結果是一樣的。

至於 prototype 究竟是什麼,下一節才會提到。

ES5 奇怪部份推薦的做法

這部分我可能之後會去找一下答案,不太清楚箇中差異,但個人蠻喜歡這樣的做法,因為我覺得蠻好懂的,畢竟就是物件罷了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var cat = {  
setName: function(name) {
this.name = name;
},
getName: function(){
return this.name;
},
sayHello: function(){
console.log(this.name + ' Meow');
}
}

var c = Object.create(cat);
var q = Object.create(cat);

console.log(c);
console.log(typeof c);
c.setName('nice');
console.log(c.getName());
c.sayHello();

console.log(c.sayHello === q.sayHello); // true

像這樣,建立一個貓物件,然後裡面定義一些方法。

接著使用 Object.create() ,這樣就結束了。

觀察後半部印出的內容,結果也與使用 class 實作出來的差別無異。

對照一下兩者內容:

而我的疑問是:

  • 以這個範例來說,可以算是物件導向的範例嗎?
    我想應該是,畢竟也有達成 MDN 對於物件導向程式設計的敘述
  • 從對照圖可以看出結構不太一樣,但我不太清楚這兩種實作方式的優劣,在實務上會推薦使用哪一種呢?

後來我找到了這兩篇

然而也想起為何奇怪部分的影片講師會比較推薦 Object.create() 的方式,以下截自上述連結文章內描述。

在其它的程式語言中,會用 class 這個關鍵字來設定該物件要長什麼樣子,然後透過關鍵字 new 來建立物件。
然而,和其他程式語言不同的地方在於,JavaScript 實際上使用的是原型繼承 (Prototypal inheritance)而不是古典繼承 (Classical Inheritance),所以為了讓 JavaScript 回歸單純的原型繼承,現在的瀏覽器大部分都支援 Object.create() 這種單純的方式來建立物件。

後來也取得了胡立大大的回應,在這邊整理一下:

  • 第一個問題,這樣也是物件導向
  • 第二個問題,實作上應該會以 class 為主, 無論是傳統的繼承方式還是原型繼承,兩者都是物件導向,而無論在哪個程式語言,就是用 class 這個語法,所以覺得最普遍而且也最容易懂

也就是說,為了方便與其他人溝通,最好還是使用 class 會是最普遍的做法。

至於 Object.creat 的部分,如果搜尋的話應該會看到 Object.create(null),意思就是要產生一個「純粹的」物件,不繼承任何的函式,所以佔用的空間最少也很乾淨,例如說只是單純想存資料的話就會使用這個方法。

後來也找到關於 Object.create(null) 的詳細敘述與範例,Vue 裡面也有運用到哦。

0%