以前在看__proto__
, prototype都會覺得天啊我不行~~太多看起來很不好理解的東西惹
可是當我查到我參考資料放的第一篇文章Javascripter 必須知道的繼承 prototype, [[prototype]], __proto__
就覺得好像突然懂了什麼?!
其實不過就是 XXX.__proto__ === YYY.prototype
嘛!
什麼意思!!?? 請繼續看下去~
__proto__
當我們在提及使用建構式函式new出來的實例可以直接繼承建構式的prototype,但新出來的實例是如何找到原型prototype的呢?靠的是一個屬性叫做__proto__
做的,他可以取回了原型物件內部的prototype當作參考。
但__proto__
是什麼意思?其實可以把它想成一個取值器, 當呼叫某物件的原型物件方法之後,它會先找自己有沒有這個方法,沒有的話就往上找,也就是說會去參考物件的原型物件prototype。
我們來看個範例:
jade.__proto__
是什麼function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.log = function () {
console.log(this.name + ", age:" + this.age);
};
var jade = new Person("jade", 18);
// 以下三個結果都一樣
console.log(jade.__proto__);
// { log: [Function (anonymous)] }
console.log(Object.getPrototypeOf(jade));
// { log: [Function (anonymous)] }
console.log(Person.prototype);
// { log: [Function (anonymous)] }
console.log(jade.__proto__ === Person.prototype);
// true
結果不論是jade.__proto__
還是Person本身的Person.prototype
都會回傳function log()
,也就是說:
__proto__
會返回物件所繼承的prototype。jade.__proto__ === Person.prototype
到這裡其實就差不多解釋完__proto__
的意思,那我們繼續往上連看會到哪裡:
console.log(jade.__proto__.__proto__ === Object.prototype);
// true
現在這個__proto__
就會指到原型物件的再上層,也就是Object.prototype
。
console.log(jade.__proto__.__proto__.__proto__);
// null
再往上一層的話,就到最頂層的null了。
於是這整條由__proto__
串接的就是原型鏈。
null
↑
Object.prototype
↑
Person.prototype
↑
jade
Object.ceate()
如何完成繼承原物件在上面一個範例可以繼承是因為讓jade物件成為Person的instance,這些是我們自己手動的,突然就好奇像是Object.ceate()
是怎麼讓物件繼承原型物件的prototype?
Object.create()
的簡單實作:
const newObject = Object.create = function(object) {
const newOobject = {}
newOobject.__proto__ = object;
return newObject;
}
Object.create()
的用法:Object.create(proto, propertiesObject)
例子:
const jade = {
name: "Jade",
age: 28,
school: "TNUA",
greet: function () {
return `here is greet by ${this.name}`;
},
};
const ann = Object.create(jade);
console.log(ann.__proto__ === jade.prototype);
// true
console.log(ann.__proto__);
// { name: 'Jade', age: 28, school: 'TNUA', greet: [Function: greet] }
在知道了Obejct.create()
是如何讓新物件可以繼承原型物件之後,可以看到ann.__proto__
會回傳整個jade的property。
因為在Obejct.create()
的時候已經讓這新物件的prototype指向整個原型物件了。
而ann.__proto__
就會是全部原型物件的property { name: 'Jade', age: 28, school: 'TNUA', greet: [Function: greet] }
__proto__
會指向原型物件的prototype先這樣拉
明天見~
參考資料:Javascripter 必須知道的繼承 prototype, [[prototype]], __proto__
你所不知道的JS 範疇與closures/this與物件原型 p.184
008天
20.1.2.2 Object.create
https://tc39.es/ecma262/#sec-object.create