var F=function(){
//this指向誰,在定義時是不知道的
};
var p=new F;
用new調用一個函數發生了這些事:
(1)新建一個對象
instance=new Object();
(2)設置原型鏈
instance.__proto__=F.prototype;
(3)讓F
中的this
指向instance
,執行F的函數體。
(4)判斷F
的返回值類型:
如果是值類型,就丟棄它,還是返回instance
。
如果是引用類型,就返回這個引用類型的對象,替換掉instance
。
注:
(1)如果沒有寫return,相當于return undefined,JavaScript中的函數都是這樣。undefined是值類型的,因此丟棄它,返回instance。
(2)如果return this相當于返回一個引用類型的對象,它自己就是instance,無所謂替換不替換了。
(3)對instance并不需要設置它的constructor屬性,這個屬性在instance的原型中。
console.assert(!p.hasOwnProperty('constructor'));
console.assert(F.prototype.hasOwnProperty('constructor'));
而且,任意一個新函數在創建時,原型的constructor就已經設置好了。
var G=function(){};
console.assert(G.prototype.hasOwnProperty('constructor'));
console.assert(G.prototype.constructor===G);
于是,這也要求我們在對prototype重新賦值的時候,重新指定constructor屬性。
F.prototype={
constructor:F
};
證明:
/* about the constructor
// instance.constructor is exactly instance.__proto__.constructor
function F() { }
console.assert((new F).constructor === F);
console.assert((new F).hasOwnProperty('constructor') === false);
console.assert(F.prototype.hasOwnProperty('constructor') === true);
// so if we change the prototype, we should also change the prototype's constructor.
function F(){}
F.prototype=new G;
F.prototype.constructor=F;
// if not, (new F).constructor===F.prototype.constructor===(new G).constructor===G.prototype.constructor===G;