iT邦幫忙

4

[筆記][JavaScript]原型(prototype)在JavaScript中的兩種意思

今天要介紹在JavaScript中會看到的「兩種原型」,這兩種原型都叫做prototype,但他們卻有完全不同的意思。

第一種的prototype為「原型關係」,一個物件為是另一個物件的原型,如以下例子:

//宣告一個物件
var objA = {
    name:'A',
};

//讓objB繼承他
var objB = Object.create(objA,{name:{value:'B'}});

//objB的原型為objA
Object.getPrototypeOf(objB) === objA; //會回傳true

//使用isPrototypeOf檢查
objA.isPrototypeOf(objB); //會回傳true

此時objB的內容會是:
https://ithelp.ithome.com.tw/upload/images/20180401/20106935AbcdalkIUP.jpg
他的__photo__屬性會有繼承而來的特性,但如果我們將這個屬性指定成其他物件:

//宣告另一個物件
var objC = {
    name:'C',
};

//把objB的__proto__指向objC
objB.__proto__ = objC;

//再去檢查會發現objB的prototype已經由objA變成objC了
Object.getPrototypeOf(objB) === objC; //會回傳true

//使用isPrototypeOf檢查
objC.isPrototypeOf(objB); //會回傳true

此時objB的內容會是如下:
https://ithelp.ithome.com.tw/upload/images/20180401/20106935RLNpvZb1VW.jpg

第二種為特性的prototype值,每個建構器都會有一個prototype的特性,他的值是一個物件,而透過這個建構器產生的實體原型都會指向這個建構器的prototype,如以下例子:

//建立一個空function
function func(){};

//把func當做建構器來創造一個實體物件
var obj = new func();

//obj這個實體物件的原型會指向建構器的prototype特性
Object.getPrototypeOf(obj) === func.prototype;  //會回傳true

//接著使用isPrototypeOf檢查
func.prototype.isPrototypeOf(obj); //會回傳true

//然後藉由建構器產生的實體物件會有constructor屬性,所以接著來判斷
obj.constructor == func; //回傳true
obj instanceof func; //回傳true

來看看obj的內容如何:
https://ithelp.ithome.com.tw/upload/images/20180401/20106935x3awaNK6JP.jpg
他在__proto__中的constructor指向建構器本身,上一篇我們知道constructor屬性可以修改,這一次我們來修改__proto__看看:

//新增一個新建構器
function func1(){};

//把obj的__proto__屬性指向新建構器的prototype屬性
obj.__proto__ = func1.prototype;

//這時候obj的原型就會從func完全變成func1了
obj.constructor == func; //就不等於原本的建構器了,會回傳false
obj.constructor == func1; //會回傳true

//接著使用instanceof、isPrototypeOf及Object.getPrototypeOf檢查
obj instanceof func1; //回傳true
func1.prototype.isPrototypeOf(obj); //會回傳true
Object.getPrototypeOf(obj) === func1.prototype;  //會回傳true

這些例子真的越試越搞混/images/emoticon/emoticon06.gif,不過可以看到不論試用何種方式去做原型的繼承或指定,最後都會存在物件中的__proto__屬性中,所以只要改變了該屬性就算是建構器的實體constructor特性也會跟著改變!!

那既然使用__proto__就可以更改原型,那他又和prototype有什麼關係呢?我們可以把他理解成prototype是屬於父母身上的基因,而他在做繼承這個動作的時候會把prototype中的基因放進孩子中的__proto__裡面,讓他也擁有相同的基因存在,不過JS的物件繼承真的是一個很難釐清的部分,說不定以後更了解了會再回來更新這篇文章/images/emoticon/emoticon37.gif,如果有說明錯誤或不明白的地方,麻煩再留言告知我,我會盡速改正!!


1 則留言

0
fysh711426
iT邦研究生 4 級 ‧ 2018-04-02 00:48:16

原來 prototype 還有兩種,
看完這篇更清楚了這段程式的用意 obj.__proto__ = func1.prototype;
也明白了建構器 prototype 屬性的用途,
我覺得你形容 prototype 是父母身上的基因還蠻貼切的,哈哈
/images/emoticon/emoticon42.gif

我要留言

立即登入留言