1. 程式人生 > 程式設計 >淺析JS中NEW的實現原理及重寫

淺析JS中NEW的實現原理及重寫

提到new,肯定會和類和例項聯絡起來,如:

function Func() {
 let x = 100;
 this.num = x +
}
let f = new Func();

上面的程式碼,我們首先建立了一個函式,如果是用面向物件的說法就是建立了一個Function類的例項,如果直接執行這個函式,那它就是一個普通的函式,如果用new執行,則這個函式被稱為一個自定義的類。

如果是一個普通函式執行,他會如下做幾件事:

  ·形成一個全新的執行上下文EC(Execution Context 執行環境)

  ·形成一個AO(Activation Object 活動物件)變數物件,初始化arguments和形參賦值

  ·初始化作用域鏈

  ·程式碼執行

如果是new函式執行,它既有普通函式執行的一面,也有自己獨有的東西:

  ·預設建立一個物件,而這個物件就是當前類的例項

  ·宣告其this指向,讓其指向這個新建立的例項

  ·不論其是否寫return,都會把新建立的例項返回,這裡有個特殊點,如果使用者自己返回內容,且返回的是一個引用型別值,則會把預設返回的例項給覆蓋掉,此時返回的值就不再是類的例項了

console.log(f); //=>{num:200}
//f是Func這個類的例項 
//相當於給建立的例項物件新增一個num的屬性 obj.num=200 (因為具備普通函式執行的一面,所以只有this.xxx=xxx才和建立的例項有關係,此案例中的x只是AO中的私有變數)
console.log(f instanceof Func); //=>TRUE instanceof用來檢測某一個例項是否屬於這個類

每一次new出來的都是一個新的例項物件

console.log(f === f2); //=>false

既然知道了new都做了什麼事情,我們重新一下new:

/* 
 * 內建NEW的實現原理 
 * @params
 *  Func:操作的那個類
 *  ARGS:NEW類的時候傳遞的實參集合
 * @return
 *  例項或者自己返回的物件
 */
function _new(Func,...args) {
  //預設建立一個例項物件(而且是屬於當前這個類的一個例項)
  let obj = {};

  //也會把類當做普通函式執行
  //執行的時候要保證函式中的this指向建立的例項
  let result = Func.call(obj,...args);

  //若客戶自己返回引用值,則以自己返回的為主,否則返回建立的例項
  if ((result !== null && typeof result === "object") || (typeof result === "function")) {
    return result;
  }
  return obj;
}

我們試一下:

let f3 = _new(Func);
console.log(f3); // =>{num: 200} 

我們繼續測試:

Func.prototype.log = function () {
  console.log('ok');
}
let f4 = _new(Func);
f4.log(); //=>Uncaught TypeError: f4.log is not a function

也就是說,Func原型上的方法其例項沒法呼叫,我們還需要修改:

/* 
 * 內建NEW的實現原理 
 * @params
 *  Func:操作的那個類
 *  ARGS:NEW類的時候傳遞的實參集合
 * @return
 *  例項或者自己返回的物件
 */
function _new(Func,...args) {
  //預設建立一個例項物件(而且是屬於當前這個類的一個例項)
  // let obj = {};
  let obj = Object.create(Func.prototype);

  //也會把類當做普通函式執行
  //執行的時候要保證函式中的this指向建立的例項
  let result = Func.call(obj,...args);

  //若客戶自己返回引用值,則以自己返回的為主,否則返回建立的例項
  if ((result !== null && typeof result === "object") || (typeof result === "function")) {
    return result;
  }
  return obj;
}

這樣應該就可以了。

let f6 = _new(Func);
f6.log(); //=>ok

總結

以上所述是小編給大家介紹的JS中NEW的實現原理及重寫,希望對大家有所幫助,也非常感謝大家對我們網站的支援!