第一種情況(無返回值)
function Person(name){
this.name=name;
this.sayName=function(){
console.log(this.name);
};
}
const a = Person('張三');//執(zhí)行了Person('張三'),但是沒有返回值
//a=執(zhí)行后的Person('張三')=無返回值=undefined
const b = new Person('李四');//新建了一個(gè)Person('李四')對象
a.sayName();//報(bào)錯(cuò)
b.sayName();//李四
window.sayName();//張三
為什么會出現(xiàn)這種情況?
- 如果聲明時(shí)沒有new,其實(shí)就是簡單的函數(shù)調(diào)用并賦值,如果函數(shù)也沒有返回值,那么函數(shù)調(diào)用并沒有什么意義,也就是說聲明的a=undefined,然后執(zhí)行了Person('張三'),但是是屬于window對象,所以執(zhí)行window.sayName()能輸出張三
- 如果聲明時(shí)有new,具體發(fā)生如下
1.創(chuàng)建一個(gè)繼承自構(gòu)造函數(shù)原型的新對象,也就是創(chuàng)建一個(gè)新的內(nèi)存空間,然后讓該內(nèi)存空間的__ proto__指向構(gòu)造函數(shù)的prototype。(繼承構(gòu)造函數(shù)的原型鏈)
2.將構(gòu)造函數(shù)中的this指向剛創(chuàng)建的內(nèi)存空間
對象的__ proto__屬性能夠訪問到原型,IE下則沒有暴露出相應(yīng)的屬性
3.使用指定的參數(shù)執(zhí)行構(gòu)造函數(shù)中的代碼
因此相當(dāng)于新建了一個(gè)Person對象,所以執(zhí)行b就是我們想要的結(jié)果
第二種情況(有返回值)
//返回?cái)?shù)值類型
function Person1(name) {
this.name = name;
return this.name;
}
var a1= new Person1('張三'); //新建了一個(gè)Object 對象,它有一個(gè)name 屬性,并且返回一個(gè)字符串test
var b1 = Person1('李四'); // 函數(shù)Test()屬于Function對象,返回"test"字符串,所以test2單純是一個(gè)字符串
console.log(a1)//Object
console.log(b1)//李四
console.log(a1.name)//張三
console.log(b1.name)//undefined
//返回引用類型
function Person2(name) {
this.name = name;
return [1,2,3];
}
var a2= new Person2('張三'); //新建了一個(gè)Object 對象,它有一個(gè)name 屬性,并且返回一個(gè)字符串test
var b2 = Person2('李四'); // 函數(shù)Test()屬于Function對象,返回"test"字符串,所以test2單純是一個(gè)字符串
console.log(a2)//[1,2,3]
console.log(b2)//[1,2,3]
console.log(a2==b2)//false
還是分兩種情況:
- 如果沒有new,但是函數(shù)有返回值,那么就會把返回值賦值給a
-
如果有new:
1.函數(shù)返回值為常規(guī)意義上的數(shù)值類型(Number、String、Boolean)時(shí),new函數(shù)將會返回一個(gè)該函數(shù)的實(shí)例對象
2.函數(shù)返回一個(gè)引用類型(Object、Array、Function)時(shí),則new函數(shù)與直接調(diào)用函數(shù)產(chǎn)生的結(jié)果相同,執(zhí)行構(gòu)造函數(shù)之后把引用類型返回
下面是chrome瀏覽器控制臺輸出的效果
Chrome控制臺
