# js手动实现一个new

要想手动实现一个new,就要知道new究竟干了什么

我们先new一下

var obj = new Test();
1

其实上面这个new就干了三件事:

var obj = {};  // 我们创建了一个空对象obj
obj.__proto__ = Test.prototype;  // 我们将这个空对象的__proto__成员指向了Test函数对象prototype成员对象
Test.call(obj);  // 我们将Test函数对象的this指针替换成obj,然后调用Test函数,于是我们就给obj对象赋值了一个id成员变量,这个成员变量的值是"test",关于函数call的用法
1
2
3

看了new干了什么后,我们就来着手实现功能了

function create(Con, ...args) {
    let obj = {};
    Object.setPrototypeOf(obj, Con.prototype);
    let result = Con.apply(obj, args);
    return result instanceof Object ? result : obj;
}
1
2
3
4
5
6

以上就是我们的完整代码,我们通过以下几个步骤实现的:

  • 首先函数接受不定量的参数,第一个参数为构造函数,接下来的参数被构造函数使用
  • 然后内部创建一个空对象 obj
  • 因为 obj 对象需要访问到构造函数原型链上的属性,所以我们通过 setPrototypeOf 将两者联系起来。这段代码等同于 obj.proto = Con.prototype
  • 将 obj 绑定到构造函数上,并且传入剩余的参数
  • 判断构造函数返回值是否为对象,如果为对象就使用构造函数返回的值,否则使用 obj,这样就实现了忽略构造函数返回的原始值

接下来我们来使用下该函数,看看行为是否和 new 操作符一致

function Test(name, age) {
    this.name = name;
    this.age = age;
}
Test.prototype.sayName = function () {
    console.log(this.name);
}
const a = create(Test, 'asa', 24);
console.log(a.name);  // 'asa'
console.log(a.age);  // 24
a.sayName()  // 'asa'
1
2
3
4
5
6
7
8
9
10
11

以上

参考链接: https://mp.weixin.qq.com/s/TIJP7pNk5_MeQzXaa1RqpQ

TOC