学习分享: 模拟一下对象的 new 命令

220 阅读1分钟

如下是 MDN 对 new 运算符的描述:

Snipaste_2021-09-20_20-12-05.png

先按照 MDN 的描述一步一步来

自定义的方法格式 myNew(constructor,[arguments1],[arguments2]...)

/*
  定义一个 myNew 方法 模拟对象的 new 关键字的功能
      参数:
          Cons     构造函数,
          ...args  接受剩余参数
*/ 
function myNew(Cons,...args){
    // 1.创建一个空对象
    const obj = {};
    // 2.为这个对象指定隐式原型属性(实例对象是没有 prototype 的)
    obj.__proto__ = Cons.prototype;
    // 3.调用构造器(使用 apply 改变里面的 this 指向 obj 并把参数传递过去)
    Cons.constructor.apply(obj,args);
    // 4.返回obj
    return obj;
}

测试代码:

function myNew(Cons,...args){
    // 1.创建一个空对象
    const obj = {};
    // 2.为这个对象指定隐式原型属性(实例对象是没有 prototype 的)
    obj.__proto__ = Cons.prototype;
    // 3.调用构造器(使用 apply 改变里面的 this 指向 obj 并把参数传递过去)
    Cons.constructor.apply(obj,args);
    // 4.返回obj
    return obj;
}
// Person 构造函数
function Person(name,age){
    this.name = name;
    this.age = age;
}

const p1 = new Person('张三',18); // 使用 new
const p2 = myNew(Person, '李四', 28); // 使用 自定义方法
console.log('我是p1',p1);
console.log('我是p2',p2);
console.log(p1.__proto__ === p2.__proto__); // 实例原型比较
console.log(p2.__proto__ === Person.prototype); // 实例与构造函数的原型对象比较

控制台输出结果:

Snipaste_2021-09-20_20-44-12.png

可以修改一下 myNew 让代码简洁一点

function myNew(Cons) {
    // Object.create 方法会返回一个 新对象,带着指定的原型对象和属性(MDN定义)
    const obj = Object.create(Cons.prototype);
    obj.info = '使用了 Object.create'; // 这个属性就是标识一下的, 没有其他意思
    // 可以只接受构造函数 其他参数使用 arguments 代替也是可以的(当然全用arguments也可以就是不美观)
    Cons.apply(obj, arguments);
    return obj;
}

同样输出:

Snipaste_2021-09-20_20-55-02.png

文章参考 juejin.cn/post/684490…