一日客語:中文:圓 客語: 眼ienˇ
昨天講述為啥修改了Cat原型後使用Object.getPrototypeOf(niki).constructor
為何是印出 Object 呢
一開始 Object.getPrototypeOf(nini).constructor
明明是Cat為何原型有這種差異呢
就繼續看下去~
function Cat() {
this.eat = () => 'apple';
}
const nini = new Cat();
Cat.prototype.sleep = 'sleep';
console.log(Object.getPrototypeOf(nini)); //{ sleep: 'sleep' }
//原型變動
//新物件改掉Cat原型
Cat.prototype = {
go: function () {
return 'go';
},
};
const niki = new Cat();
console.log(Object.getPrototypeOf(niki)); //{ go: [Function: go] }
Object.getPrototypeOf(niki).constructor//Object
instanceof :niki instanceof Cat
判斷實例是不是透過建構器函式建立的
constructor:實例.constructor
可以找到創建實例的建構函式
wendy instanceof Wendy
運作方式:
會先查Wendy的原型
此原型是否出現在wendy的原型鏈上
function Wendy() {}
function Ann() {}
Ann.prototype = new Wendy(); //目前 Ann.prototype ={}
const smallAnn = new Ann();
console.log(smallAnn instanceof Ann);//true
//Ann的原型是否出現在smallAnn上
console.log(smallAnn instanceof Wendy);//true
//Wendy的原型是否出現在smallAnn上
實例.constructor:實例的原始函式參照(物件的起源)
要注意一件事情:let a = new Apple()
什麼property都沒有只剩下[[prototype]]
點開[[prototype]]
,從這區開始(記得這裡是物件喔)會是Apple.prototype
此時就要想想,prototype是建構函式才會有,就要思考來自哪個函式就會是他的constructor
所以a.constructor
是來自Apple的prototype
這個prototype是因為Apple function 才有的,所以constructor是Apple
(忍耐一下這邊是需要停下來好好思考的,想個幾次就會海闊天空)
function Cat() {
this.eat = () => 'apple';
}
const nini = new Cat();
console.log(nini.constructor);//[Function: Cat]
function Dog() {
this.sleep = () => 'sleep';
}
const doggy = new Dog();
console.log(doggy.constructor);//Function: Dog]
兩個實例一個nini和一個doggy 找找他們建構子
可以看到nini.constructor和doggy.constructor的原始函式參照是[Function: Cat]
和[Function: Dog]
可以說是 nini.constructor等同於Cat
因此可以使用 nini.constructor來創建新物件
function Cat() {
this.eat = () => 'apple';
}
const nini = new Cat();
const kiki = new nini.constructor();//我直接找Cat function的參照來建立實例
console.log('nini使用建構函式創出', nini);
//nini使用建構函式創出 Cat { eat: [Function (anonymous)] }
console.log('kiki使用nini的建構子創出', kiki);
//kiki使用nini的建構子創出 Cat { eat: [Function (anonymous)] }
console.log(nini.constructor == kiki.constructor);//true
console.log(nini instanceof Cat);//true
nini.constructor
和 kiki.constructor
都是同樣的指向Cat
也可以試試看基本型別
let name = 'wendy';
let mystring = name.constructor('abc');
console.log(mystring);//'abc'
name由String()
產生的實例所以他的mystring.__proto__
會是String的prototype
String的prototype內屬性:[[prototype]]
會是Object的prtotype
Object的prtotype內屬性[[prototype]]
會是null
會了這些,繼續講昨天的疑問
function Cat() {
this.eat = () => 'apple';
}
const nini = new Cat();
Cat.prototype.sleep = 'sleep';
console.log(Object.getPrototypeOf(nini));
//{ sleep: 'sleep' }
//改變Cat的原型
Cat.prototype = {
go: function () {
return 'go';
},
};
const niki = new Cat();
console.log(nini instanceof Cat); //Cat原型是否出現在nini上:false
console.log(nini.constructor); //[Function: Cat]
// 那新實例(niki)呢?
console.log(niki instanceof Cat);///Cat原型是否出現在niki上:true
console.log(niki.constructor); //[Function: Object]
問題:為何niki.constructor 印出是[Function: Object]
因為
//這是Cat修改後的原型(沒有constructor屬性)
{ go: function () {
return 'go';
}, }
這個object沒有constructor屬性,通常建構函式的prototype內有constructor屬性,因為修改了建構函式的prototype所以constuctor消失了!!!
所以跑的這句niki.constructor,其實niki會往上一層找到Cat的prototype
但自建object 沒有constructor,所以會根據原型鏈再往上找,
找到{ }本身的[[prototype]]
裡的constructor
會像是長這樣
此時這區是Object地盤(是大寫O),他是建構函式的其中一種,因此他的prototype裡會有constructor,Object.prototype.constructor
登愣!!!
所以niki才會印出Object
1.複製別人的方法/屬性
把constructor的prototype的某一個methods複製過來,
像是底下把Wendy.prototype.sleep
methods貼到另一個建構函式的methods內
function Wendy() {}
Wendy.prototype.sleep = '今天睡滿24hr,超爽的';
Wendy.prototype.eat = '今天吃滿24hr';
function Ann() {}
Ann.prototype = { goSleep: Wendy.prototype.sleep }; //wendy 的sleep能力掛在ann身上
const a = new Ann();
console.log(a.goSleep);//今天睡滿24hr,超爽的
console.log(a.eat);//undefined
console.log(a instanceof Ann); //true
console.log(a.constructor); //[Function: Object]
這只是複製不是繼承
console.log(a instanceof Wendy); //false
那要說說繼承了~~
function Go() {}
function Run() {}
Go.prototype.school = 'sleep';
Run.prototype = new Go();
const student = new Run();
console.log(student instanceof Go);//true
console.log(student instanceof Run);//true
console.log(student.school);//sleep
Go的原型換成new Go()物件實例
透過student物件來存取school方法,JS執行環境會先對student物件找尋有沒有school方法,沒有方法就回去找他的原型:Go物件
先到這裡~明天再接再厲