最近在看手写new
,涉及到原型对象和隐式原型,虽然现在手写new
已经不会明显地操作__proto__
了,但我们还是要明白,关于原型的内容有点多,写在另一篇里面了。
先看现在的手写new
的代码:
function _new(fn) {
const obj = Object.create(fn.prototype)
const rel = fn.apply(obj, [arguments])
return rel instanceof Object ? rel : obj
}
先单句解析:
const obj = Object.create(fn.prototype)
这一句里面发生了如下事件:- 创建一个空对象
{}
- 空对象的
__proto__
获得fn.prototype
的属性和方法 - 那
obj
获得了什么? 答案是啥都没得到,但他的__proto__
得到了想要的一切
- 创建一个空对象
const rel = fn.apply(obj, [arguments])
- 执行
fn
,但此时fn
内部的this
指向了obj
,arguments
也归obj
所有 - 此时
fn
内部的this.xxx = xxx
等操作将使obj
真正获得xxx
属性
- 执行
return rel instanceof Object ? rel : obj
- 如果
rel
是对象,那说明fn
执行时返回了一个更完善的对象,我们就用这个(因为fn
作为构造函数,极有可能自己在内部进行一番操作,比如赋值一些特殊的在Object.create
阶段没赋予obj
的方法,弄出一个我们真正需要的对象) - 如果返回值为
undefined
,说明没有返回值,我们操作完this
和参数的传递就可以直接返回obj
了
- 如果
这是现在比较常见的手写new
方式
以前会这么写:
function _new(fn) {
var obj = {
}
obj.__proto__ = fn.prototype
const rel = fn.apply(obj, [arguments])
return rel instanceof Object ? rel : obj
}
我们会发现步骤其实和上面的第一句解析一个意思。
现在我们不推荐使用__proto__
了。
下一篇介绍原型。