今天看到一道面試題,以下,問: 實例化 Person
過程當中,Person
返回什麼(或者 p
等於什麼)?git
function Person(name) {
this.name = name
return name;
}
let p = new Person('Tom');
複製代碼
說實話,第一反應我覺得值爲 'Tom'
,等到我把代碼丟到控制檯一輸出,才明白我錯了。天吶,new
運算符給無視掉了嗎??? 撇開 new
的存在,咱們修改下代碼github
function Person(name) {
this.name = name
return name;
}
let p = Person('Tom');
console.log(p);
複製代碼
很顯然,輸出的結果是 'Tom'
, 可是有 new
存在呢?接下去,咱們來捋一捋。 首先,我先去 MDN上搜索了 new 的定義面試
new 運算符建立一個用戶定義的對象類型的實例或具備構造函數的內置對象的實例。數組
emmmm,至關晦澀難懂。app
那咱們試着寫幾個栗子看看結果吧函數
function Person1(name) {
this.name = name;
// 沒有返回值
}
function Person2(name) {
this.name = name;
return name;
// 返回非對象
}
function Person3(name) {
this.name = name;
return { a: 1 };
// 返回對象
}
function Person4(name) {
this.name = name;
return null;
// 返回null
}
var p1 = new Person1("aa");
var p2 = new Person2("bb");
var p3 = new Person3("cc");
var p4 = new Person4("dd");
console.log(p1); // Person1 {name: "aa"}
console.log(p2); // Person2 {name: "bb"}
console.log(p3); // {a: 1}
console.log(p4); // Person4 {name: "dd"}
複製代碼
根據上面幾個栗子,咱們能得出結論:當使用 new 來建立對象||調用構造函數時,若是函數沒有返回值|| 返回值是非對象,那麼返回的就是構造函數實例後的對象(注意:return null
,返回的也是構造函數實例後的對象而非null
);若是函數return對象,那麼返回這個對象學習
咱們接着看 MDN 文檔的解釋,畢竟光光看這幾個demo沒有說服力。ui
一塊兒來理解下 new
到底作了什麼工做吧~ 就拿下面這個 demo
分析this
function Person(name) {
this.name = name;
return {a: 1}
}
var p = new Person('fe')
複製代碼
當調用 new Person(...)
時,會進行如下幾步:spa
Person.prototype
的新對象會被建立'fe'
調用構造函數 Person
, 並將 this
綁定到新建立的對象Person
返回的對象就是 new
表達式的結果 =》 Person
返回的對象是 {a: 1}
因此new
表達式的結果爲 {a:1}
; 若是 Person
沒有返回值(通常構造函數都不返回值)那麼使用步驟1建立的對象,即==》 繼承自 Person.prototype
的新對象貌似照着文檔可以些許理解了,假若模擬實現 new
運算符更能深刻理解 new
如下是 new 的模擬實現,代碼來源 : JavaScript深刻之new的模擬實現
function objectFactory() {
var obj = new Object(),
cons = [].shift.call(arguments)
obj.__proto__ = cons.prototype
var ret = cons.apply(obj, arguments)
return typeof ret === 'object' ? ret|| obj : obj
}
function Person(name) {
this.name = name;
return {a: 1}
}
var p = objectFactory(Person, 'fe')
複製代碼
固然了,學習別人的代碼不能僅僅只是照搬過來,起碼得理解這個代碼吧。 使用
cons
是調用 objectFactory
方法的第一個參數,即構造函數; 由於 shift
會改變原數組,因此改變後的 argument
即爲調用構造函數的參數 (這裏補充說明下: arguments 是一個對應於傳遞給函數的參數的類數組對象。)obj
的原型指向構造函數, 這樣 obj 就能訪問到構造函數原型上的屬性cons
的 this
指向 obj
,這樣 obj
能訪問構造函數裏的屬性return null
的特例,由於歷史遺留問題 typeof null === 'object'
);若是不是對象就返回 obj
(注意:這裏的 obj
已經不是一個空對象)若是你耐心看到了這裏,那麼十分感謝。如文章有錯誤,望給予指正~