深刻一点 - 用 new 的时候到底发生了什么?

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

咱们常常用new来建立一个对象,可是建立对象过程当中,到底发生了什么呢?git

new 操做符的过程


上面是mdn的定义。github

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

模拟 new 函数来建立对象。

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

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

很简单一个例子,建立一我的。this

建立一个空对象并连接到传入对象中

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

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

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传入。prototype

返回判断

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;
}

判断结果,并返回。code

跑一下例子

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 属于左值表达式(表明数值位于=号的左侧)
blog

这是在规范过程,在规范中分为两个状况,有参数状况和无参数状况,空参数状况按照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...

相关文章
相关标签/搜索