先看一下如下例項程式碼
function Person(name,age){
this.name=name;
this.age=age;
}
Person.prototype.say=function(){
console.log("姓名:"+this.name+",年齡:"+this.age);
}
var p1=new Person("黎明",30);
console.log(p1.name);//黎明
p1.say();//姓名:黎明,年齡:30
複製程式碼
1、new在這個過程中執行了以下三個步驟
1、建立一個空物件;
2、然後讓這個空物件的__proto__指向函式的原型prototype,繼承了該函式的原型。
3、呼叫call方法,將這個空物件物件作為函式的this傳進去,並且最後隱式的返回這個空物件 。
2、呼叫建構函式使用new關鍵字的情況
var p1=new Person("黎明",30)這句程式碼的內部程式碼執行如下:
new Person("黎明",30)={
var obj = {};//建立一個空物件
obj.__proto__ = Person.prototype;
Person.call(obj,"黎明",30);
return obj;
}
複製程式碼
分析:所以new在這個過程中的作用是,使p1繼承了Person的name和age屬性,使p1的原型指向了Person的原型,使得p1擁有了Person的全部例項屬性和原型物件,因此p1具有了name和age屬性以及say方法。new Person("黎明",30)返回的是如下所示的物件
3、呼叫建構函式不使用new關鍵字的情況
var p2=Person("李明",24);
console.log(p2.name);//Cannot read property 'age' of undefined
複製程式碼
分析:此時相當於只是呼叫了Person("李明",24)的這樣一個普通方法,並不是呼叫Person建構函式建立一個新的例項物件,並且該方法沒有返回值,所以呼叫Person("李明",24)返回的是預設值undefined。因此P2也沒有name和age屬性。
var p2=Person("李明",24)
p1.say.call(p2);//"姓名:李明,年齡:24
複製程式碼
為什麼這句程式碼會有輸出呢?原因如下
1、var p2=Person("李明",24);在Person構造方法中的this表示的是window,所以就有;
window.name="李明";
window.age=24;
複製程式碼
2、p1.say.call(p2)中的p2表示是呼叫Person("李明",24)建構函式後的返回值,但是該建構函式沒有返回值,因此p2=undefined,根據call方法的定義,所以在say()方法中的this表示window。
4、呼叫建構函式時,在內部有retun語句的情況
function Person(name,age){
this.name=name;
this.age=age;
return name;
}
var p1=new Person("黎明",23);
console.log(p1);//{name: "黎明",age:23}
複製程式碼
function Person(name,age){
this.name=name;
this.age=age;
return {};
}
var p1=new Person("黎明",23);
console.log(p1);//{}
複製程式碼
原因分析:建構函式不需要顯示的返回值。使用new來建立物件(呼叫建構函式)時,如果return返回的是非物件(數字、字串、布林型別等)會忽略返回值;如果return的是物件,則返回該物件(注:若return null也會忽略返回值)。