2
来自:https://zswfx.com/articles/5db9285f9cf7c10e840e5c6a

我们经常用new来创建一个对象,但是创建对象过程中,到底发生了什么呢?

new 操作符的过程


上面是mdn的定义。

通过上面定义,我们知道使用new的时候,JS引擎就会给我们创建一个空对象作为 this值,然后执行函数,若函数没有返回值,则默认返回这个空对象

模拟 new 函数来创建对象。

根据上面mdn定义new过程,我们来模拟一下new的过程,只有模拟后,我们就知道使用new后,引擎是如何操作的,咦下面例子为例:

function Person(name, age) {
    this.name = name;
    this.age = age;  
}

很简单一个例子,创建一个人。

创建一个空对象并链接到传入对象中

function mockNew(...args) {
  const Constructor = args[0];
  const object = Object.create(Constructor.prototype);
}

在这里,通过 Object.create 创建新对象,并把新对象 __proto__ 指向传入对象的 prototype.

Object.create 查看这里

把新对象作为上下文注入

function mockNew(...args) {
  const Constructor = args[0];
  const object = Object.create(Constructor.prototype);
  const params = args.slice(1);
  Constructor.apply(object, params);
}

通过 apply 函数,将object当成 this传入。

返回判断

function mockNew(...args) {
  const Constructor = args[0];
  const object = Object.create(Constructor.prototype);
  const params = args.slice(1);
  const ret = Constructor.apply(object, params);
  return ret || object;
}

判断结果,并返回。

跑一下例子

function Person(name, age) {
  this.name = name;
  this.age = age;
}

const pe = mockNew(Person, '战三', 23)
console.log(pe);

通过对比,发现一抹一样。我们就模拟的整个new 的过程。

规范上过程

es有规范,规范位于 11.2.2 new 运算符new 属于左值表达式(代表数值位于=号的左侧)

这是在规范过程,在规范中分为两个情况,有参数情况和无参数情况,空参数情况按照NewExpression: new NewExpression的左值表达式方式执行,执行的事函数无参数情况,有参数则是按照 MemberExpression: new MemberExpression Arguments 方式执行,都有关于异常处理情况,不同的是第二种会去获取函数参数列表,并传入[[Construct]] 内。

NewExpression: new NewExpressionMemberExpression: new MemberExpression Arguments 均是左值表达式

总结

直接用mdn上的描述吧:

创建一个对象类型,需要创建一个指定其名称和属性的函数;对象的属性可以指向其他对象,看下面的例子:

当代码 new Foo(...) 执行时,会发生以下事情:

  1. 一个继承自 Foo.prototype 的新对象被创建。
  2. 使用指定的参数调用构造函数 Foo,并将 this 绑定到新创建的对象。new Foo 等同于 new Foo(),也就是没有指定参数列表,Foo 不带任何参数调用的情况。
  3. 由构造函数返回的对象就是 new 表达式的结果。如果构造函数没有显式返回一个对象,则使用步骤1创建的对象。(一般情况下,构造函数不返回值,但是用户可以选择主动返回对象,来覆盖正常的对象创建步骤)

源码地址: https://github.com/zsirfs/con...


zsirfs
832 声望24 粉丝

菜鸟挣扎努力的去学习