iT邦幫忙

4

[筆記][JavaScript]建構器及實體物件的constructor特性

HI,大家好!因為之後會提到建構器間的繼承,所以在那之前先提一下constructor這個特性的用途,這個特性在前兩篇的[筆記][JavaScript]使用建構器創造實體物件[筆記][JavaScript]原型(prototype)在JavaScript中的兩種意思都有稍微提過,讓我們用這一篇文章再來加深一些印象。

一般來說,每個函式都會有一個原型物件function.prototype,而他的特性constructor會指向函式自己,以下例子:

//宣告一個空函式
function Func(){};
//去判斷他原型中的constructor特性
Func.prototype.constructor; //會回傳func本身
//拿來和函式本身比較
Func === Func.prototype.constructor; //會回傳true

好,再來就像之前說的,使用建構器創造出來的實體物件也會有一個constructor特性,這時候的constructor也會指向建構器本身,以下例子:

//宣告一個空函式用來當建構器使用
function Func(){};
//使用該建構器建構一個實體物件
var obj = new Func();
//來試著判斷實體物件中的constructor特性
obj.constructor; //會回傳func本身
//接著直接比較看看
obj.constructor === Func; //會回傳true

接著我們統整一下上述的觀念,在一個建構器FuncFunc.prototype.constructor;和他建構出來的實體物件的constructor特性都會指向Func本身,所以我們可以用一個實體物件來建構出有相同建構器的實體物件,以下例子:

//宣告一個空函式用來當建構器使用
function Func(){};
//使用該建構器建構一個實體物件
var objA = new Func();
//經過上面的例子我們可以知道objA.constructor會等於建構器本身
Func === objA.constructor; //回傳true
//使用objA來建立一個擁有相同建構器的實體物件
var objB = new objA.constructor();
//用instanceof判斷是否為建構器Func的實體物件
objB instanceof Func; //回傳true

另外順便提一下建構器中的prototype特性,通常每個函式都會有該特性,而且我們不會去取代這個特性原本有的內容(例如constructor),而是在該特性中建立新的方法。以下範例:

//宣告一個空函式
function Func1(){};
//通常是不會去取代他的prototype,就像以下這樣
Func1.prototype = {
    writeThis:function(){
        console.log(this);
    },
};

//為了避免蓋掉prototype,所以我們會在原本的prototype中建立方法
//宣告一個空函式
function Func2(){};
//在原本的prototype中新增方法
Func2.prototype.writeThis = function(){
    console.log(this);
};

以上例子的技巧可以使用在必須處理某個建構器的實體,並且想要建立出和某個實體相同的方法來說很方便,更進一步可以把該方法寫進建構器的prototype中來使用:

//宣告一個空函式來當建構器使用
function Func(){};
//在該建構器的prototype建立一個方法特性
Func.prototype.copyObj = function(){
    return new this.constructor();
};
//先建構一個實體物件
var objA = new Func();
//使用該實體物件繼承來的copyObj方法來建構第二個有同樣建構器的實體物件
var objB = objA.copyObj();
//最後來判斷他是否為建構器Func的實體物件
objB instanceof Func; //回傳true

以上是對constructor特性的一些說明和應用,如果有說明錯誤或不明白的地方,麻煩再留言告知我,我會盡速改正!!


1 則留言

3
henry35208
iT邦新手 5 級 ‧ 2018-04-10 14:03:02

過度依賴 constructor 可能不太好。

就像文章中所講的 constructor 是可以被更改的,且也是可能發生的情境,

例如在 ES5 前的繼承是使用以下方式來實作:

Child.prototype = Object.create(Parent.prototype);

此時如果忘記手動修復 constructor 的話,Child.prototype.constructor 就會是 Parent

因此應該盡量避免對 constructor 操作,若要檢查型別的話,使用 instanceOfObject.isPrototypeOf 甚至是 Object.getPrototypeOf 等函式都會是比較安全的。不過發現這點其實大大之前也提過呢!

對,感謝大大的補充!!
因為這篇文章想說提一下constructor能夠做到的事情,卻忘了提醒大家該注意的事情,真的非常抱歉/images/emoticon/emoticon06.gif

我要留言

立即登入留言