来自: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 NewExpression
和MemberExpression: new MemberExpression Arguments
均是左值表达式
总结
直接用mdn上的描述吧:
创建一个对象类型,需要创建一个指定其名称和属性的函数;对象的属性可以指向其他对象,看下面的例子:
当代码 new Foo(...) 执行时,会发生以下事情:
- 一个继承自 Foo.prototype 的新对象被创建。
- 使用指定的参数调用构造函数 Foo,并将 this 绑定到新创建的对象。new Foo 等同于 new Foo(),也就是没有指定参数列表,Foo 不带任何参数调用的情况。
- 由构造函数返回的对象就是 new 表达式的结果。如果构造函数没有显式返回一个对象,则使用步骤1创建的对象。(一般情况下,构造函数不返回值,但是用户可以选择主动返回对象,来覆盖正常的对象创建步骤)
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。