都2020年了,你應該知道如何手寫New了吧

接着上一篇,咱們繼續來研究如何手寫。web

1、手寫new

1.new運算符都作了什麼

  1. 新建一個對象。
  2. 執行prototype鏈接。
  3. 將構造函數的做用域賦給新對象。
  4. 綁定this指向,執行構造函數中的代碼。
  5. 返回這個對象。

2.簡單實現

function myNew(context) {

    // 新建一個對象
    var res = new Object();
    
    // 獲取傳遞的參數,第一個參數表明傳入的構造函數,也就是這個即將建立的這個實例的構造函數,截取掉
    const args = [...arguments].slice(1);
  
    // 將建立的res的this綁定到傳進來的這個構造函數context
    context.apply(res, args);
  
    return res;
}

function Hdove(name) {
  this.name = name;
}

var example = myNew(Hdove, 'LJ');

console.log(example); // {name: "LJ"}

複製代碼

3.繼續改造

來,咱們先看一下真實的new操做符bash

function Hdove(name) {
  this.name = name;
}

Hdove.prototype.age = 25;

Hdove.prototype.sayName = function() {
    console.log(this.name);
};

var obj = new Hdove('LJ');

console.log(obj.name); // LJ
console.log(obj.age); // 25
obj.sayName(); // LJ

複製代碼

繼續修改咱們的代碼app

function myNew(context) {

    var res = new Object();
    
    // 判斷構造函數上有沒有原型,有的話進行添加
    if(context.prototype) {
        res.__proto__ = context.prototype
    }
    
    const args = [...arguments].slice(1);
  
    context.apply(res, args);
  
    return res;
}

function Hdove(name) {
  this.name = name;
}

Hdove.prototype.age = 25;

Hdove.prototype.sayName = function() {
    console.log(this.name);
};

var example = myNew(Hdove, 'LJ');

console.log(example);

經過下圖咱們能夠看出原型已經成功綁定了,完美

複製代碼

距離成功還有一步,咱們加足馬力函數

4.改造升級

咱們繼續看一下原生的new 操做符post

1.返回一個對象
function Hdove(name) {
  this.name = name;
  return {
    name: 'return出來的'
  }
}

var obj = new Hdove('LJ');  
console.log(obj); // {name: "return出來的"}

2.返回基本類型
function Hdove(name) {
  this.name = name;
  return '123';
}


var obj = new Hdove('LJ');  
console.log(obj); // {name: "LJ"}

3.返回一個方法
function Hdove(name) {
  this.name = name;
  return function() {
    console.log(123);
  };
}


var obj = new Hdove('LJ');  
console.log(obj); // function () { window.runnerWindow.proxyConsole.log(123); }

複製代碼

有沒有發現神奇的事情發生了,當咱們在構造函數中返回一個對象類型A的時候,這個時候咱們使用new操做符,實際上返回的就是這個A,反之,返回的是咱們新建的這個對象,開始實現!ui

function myNew(context) {

    var res = new Object();
    
    // 判斷構造函數上有沒有原型,有的話進行添加
    if(context.prototype) {
        res.__proto__ = context.prototype
    }
    
    const args = [...arguments].slice(1);
  
    const ret = context.apply(res, args);
    
    // 判斷ret 是否是object或者function,由於null也屬於object,因此要單獨排除
    if((typeof ret === 'object' || typeof ret === 'function') && ret !== null) {
      return ret;
    }
    return res;
}

function Hdove1(name) {
  this.name = name;
}

function Hdove2(name) {
  this.name = name;
  return {
    name: 'return出來的數據'
  }
}

var example1 = myNew(Hdove1, 'LJ');
var example2 = myNew(Hdove2, 'LJ');

console.log(example1); // { name: LJ }
console.log(example2); // { name: return出來的數據 }

複製代碼

5.完整版

function myNew(context) {

    var res = new Object();
    
    if(context.prototype) {
        res.__proto__ = context.prototype
    }
    
    const args = [...arguments].slice(1);
  
    const ret = context.apply(res, args);
    
    if((typeof ret === 'object' || typeof ret === 'function') && ret !== null) {
      return ret;
    }
    return res;
}

複製代碼

6.推薦閱讀

相關文章
相關標籤/搜索