看了冴羽的Javscript博客,同样模拟一下new
的功能实现
对于new操作符的认识
首先,是使用new
的两种方式:
1 | function Person(name) {this.name = name}; |
其次,简单看一下new
的大致流程:
执行Construct(constructor, argList)
,这里如果没问题的话,最终会执行constructor.[Construct](argumentsList,newTarget)
,所以直接看最终的抽象操作:
argumentsList
为参数列表(类数组),newTarget
最开始没有指定的话就是constructor
。- 赋
callerContext
为running execution context
(当前运行的执行上下文)。 - 赋
kind
为F.[[ConstructorKind]]
。F
为constructor
;F.[[ConstructorKind]]
的可能取值为:base
或derived
。一般定义函数的时候,这个ConstructorKind
都为base
。 - 如果
kind
为base
,则- 赋
thisArgument
为一个[[Prototype]]
指向Constructor.prototype
的新对象。
- 赋
- 赋
calleeContext
为当前执行上下文栈的顶部执行上下文。这一步相当于创建了执行上下文环境等预置工作。 - 把
thisArgument
绑定到当前的上下文环境中。 - …词法环境、函数作用域的构建…
- 执行函数
constructor
,结束后,从执行上下文栈中移除calleeContext
。判断constructor
返回值是否为对象,如果返回值是对象,则利用这个对象作为返回值,否则使用thisArgument
作为返回值。
简单说就是:
- 函数调用 +
this
的生成。 - 相比于函数调用,在函数返回值的时候也做了
this
的相应处理。 this
是一个[[Prototype]]
指向Constructor.prorotype
的新对象。
模拟new的实现
1 | function myNew(fn, ...arguments) { |
在创建thisArgument
创建对象的时候,有一个巨大的坑,如果用:
1 | let thisArgument = Object.create(null); //空对象 |
这样做是无法关联thisArgument
和fn.prototype
的,由于空对象不具有原型,也不具有constructor
,所以设置__proto__
相当于单纯的设置属性,而不是在设置它的原型!
空对象只要用来存储数据就行了!