New的原理

😾 New的原理

new 關鍵詞的主要做用就是執行一個構造函數、返回一個實例對象,在 new 的過程當中,根據構造函數的狀況,來肯定是否能夠接受參數的傳遞。下面咱們經過一段代碼來看一個簡單的 new 的例子

🍊 new的執行過程

new 操做符能夠幫助咱們構建出一個實例,而且綁定上 this,內部執行步驟可大概分爲如下幾步:
  • 📕 建立一個新對象
  • 📕 對象鏈接到構造函數原型上,並綁定 this(this 指向新對象)
  • 📕 執行構造函數代碼(爲這個新對象添加屬性)
  • 📕 返回新對象

例外

若是不用 new 這個關鍵詞,結合上面的代碼改造一下,去掉 new,會發生什麼樣的變化呢?咱們再來看下面這段代碼
// 'use strict';

function Person() {
    this.name = "江小白";
}

var p = Person();
console.log(p); //undefined
console.log(name) //江小白
console.log(p.name); // Cannot read property 'name' of undefined
  • 📔 從上面的代碼中能夠看到,咱們沒有使用 new 這個關鍵詞,返回的結果就是 undefined。其中因爲 JavaScript 代碼在默認狀況下 this 的指向是 window,那麼 name 的輸出結果就爲江小白,這是一種不存在 new 關鍵詞的狀況。
  • 📔 那麼當構造函數中有 return 一個對象的操做,結果又會是什麼樣子呢?咱們再來看一段在上面的基礎上改造過的代碼。
function Person() {
    this.nem = "江小白";
    return { age: 22 };
}

var p = new Person();
console.log(p); //{ age: 22 }
console.log(p.name); //undefined
console.log(p.age); //22

經過這段代碼又能夠看出,當構造函數最後 return 出來的是一個和 this 無關的對象時,new 命令會直接返回這個新對象,而不是經過 new 執行步驟生成的 this 對象app

可是這裏要求構造函數必須是返回一個對象,若是返回的不是對象,那麼仍是會按照 new 的實現步驟,返回新生成的對象。接下來仍是在上面這段代碼的基礎之上稍微改動一下函數

function Person(){
   this.name = '江小白'; 
   return 'tom';
}
var p = new Person(); 
console.log(p)  // {name: '江小白'}
console.log(p.name) // 江小白
💝 所以咱們總結一下: new 關鍵詞執行以後老是會返回一個對象,要麼是實例對象,要麼是 return 語句指定的對象

✏️ 手寫實現new

//  手寫模擬new
function myNew(fn, ...args) {
    if (typeof fn !== 'function') {
        throw 'fn mast be a function';
    }
    // 1. 用new Object()建立一個對象obj
    var obj = new Object();
    // 2. 給該對象的__proto__賦值爲fn.prototype,即設置原型鏈
    obj.__proto__ = Object.create(fn.prototype);
    // 3. 執行fn,並將obj做爲內部this。使用 apply,
    // 改變構造函數 this 的指向到新建的對象,
    // 這樣 obj 就能夠訪問到構造函數中的屬性
    var result = fn.apply(obj, args); 
    // 4. 若是fn有返回值,則將其做爲new操做返回,不然返回obj
    return result instanceof Object ? result : obj;
}

🔖 test

// test 
function Person(...args) {
  console.log(args)
}
// 使用內置函數new
var person1 = new Person(1,2)
console.log(person1)
// 使用手寫的new,即create
var person2 = myNew(Person, 1, 2)
console.log(person2)
new 被調用後大體作了哪幾件事情
  • 📒 讓實例能夠訪問到私有屬性;
  • 📒 讓實例能夠訪問構造函數原型(constructor.prototype)所在原型鏈上的屬性;
  • 📒 構造函數返回的最後結果是引用數據類型。
相關文章
相關標籤/搜索