題目
實現(xiàn)一個構(gòu)造器函數(shù)A糊肠,同時支持var a = new A()與var a = A()兩種形式擂啥,且支持A類的繼承
首先支持new作用是比較容易實現(xiàn)的(應(yīng)該是我們拿到這個題目立馬能寫出來的)
function A(){
this.name = 'John';
}
A.prototype.say = function(){
console.log(`I am ${this.name}`);
}
思路
既然new關(guān)鍵字可以幫我們完成一系列的對象實例化工作扳还,那么當A作為普通函數(shù)被調(diào)用時也可以在函數(shù)內(nèi)部實現(xiàn)new的整個過程才避,這樣就可以解決問題啦。應(yīng)該有同學想到直接調(diào)用下new是吧氨距,哈哈哈~桑逝,我覺得這也太省事了,自己實現(xiàn)new的過程豈不更爽俏让!接下來應(yīng)該區(qū)分A是在哪種形式下被調(diào)用的楞遏,根據(jù)不同的調(diào)用方式做不同的處理。
問題
- 1首昔、A作為普通函數(shù)調(diào)用時如何實現(xiàn)new的效果
問題可以轉(zhuǎn)換為new的過程做了什么寡喝?
var a = {};
a.__proto__ = A.prototype; //繼承構(gòu)造函數(shù)原型的屬性和方法
var result = A.apply(a, arguments); //擁有A的實例屬性和方法
return type result === 'object' ? result : a;
- 2、如何區(qū)分A當前是作為構(gòu)造器使用還是普通函數(shù)調(diào)用
首先要清楚一點勒奇,var a = new A()拘荡,此時A中的this指向的是a實例;var a = A()撬陵,此時this指向的是window(瀏覽器中)珊皿,因此我們可以根據(jù)this是否是A的實例來區(qū)分函數(shù)的調(diào)用方式,從而進行不同的處理巨税。
解決了上面兩個問題蟋定,再試著把A函數(shù)改寫下
實現(xiàn)
function A(){
if(!(this instanceof A)){
var a = {};
a.__proto__ = A.prototype; //a是A的實例
A.apply(a, arguments);
return a;
}else{
this.name = 'John';
}
}
A.prototype.say = function(){
console.log(`I am ${this.name}`);
}
var a1 = new A();
var a2 = A();
a1.name; //'John'
a2.name; //'John'
a1.say === a2.say; //true
Yeah~