一道面試題引起的思考:理解 new 運算符

今天看到一道面試題,以下,問: 實例化 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 就能訪問到構造函數原型上的屬性
  • 將構造函數 consthis 指向 obj,這樣 obj 能訪問構造函數裏的屬性
  • 判斷返回的值是否是一個對象,若是是對象即返回它(固然這裏要處理 return null 的特例,由於歷史遺留問題 typeof null === 'object');若是不是對象就返回 obj (注意:這裏的 obj 已經不是一個空對象)

若是你耐心看到了這裏,那麼十分感謝。如文章有錯誤,望給予指正~

相關文章
相關標籤/搜索