Open AwakenedSomeone opened 3 years ago
今天刚好看到一个东西,可用用上对应的 用代码模拟new的过程,首先还是步骤:new调用函数过程中到底发生了什么
用代码来实现一个new
function Constructor(fn, args) {
// fn的prototype属性内容作为新对象的原型内容
var _this = Object.create(fn.prototype);
var res = fn.apply(_this, args);
return res ? res : _this;
}
接下来用上述知识验证
function Foo() {
console.log(2)
}
var a = Object.create(Foo)
console.log('a.__proto__ === Foo:', a.__proto__ === Foo) // true
var b = new Foo()
console.log('b.__proto__ === Foo.prototype:', b.__proto__ === Foo.prototype) // true
// 调用自定义得new
var d = Constructor(Foo)
console.log('d.__proto__ === Foo.prototype:', d.__proto__ === Foo.prototype) // true
这里记一下原型继承相关的知识点:
从上面的例子我们可以看出来。Object.create和new的实现方式有很大不同,create创建出来的对象a,a.proto指向了Foo,而new 出来的对象b,b.proto 指向的是prototype。 我们来分析一下原因:先来看看Object.create的polyfill代码:
从这段代码可以看出来,create函数比new 多做了一个操作,那就是先将F.prototype关联到了传入的对象上,也就是上例的Foo,然后再返回了 new F()的实例。因为a.proto === F.prototype (下面说new的时候会说到), 而F.prototype 又在create内部指向了o(即是Foo),所以a.proto=== Foo 为true。 再来分析一下new Foo(),熟悉new这个过程的小伙伴知道: ①创建一个空对象 obj。 ②让空对象obj.proto指向Foo.prototype。 ③将Foo的执行上下文绑定到obj上,并存起来result。 ④如果Foo是一个对象,则返回result,如果不是则返回新创建的这个对象obj。 从这个流程可以看到,new执行构造函数调用的过程中,将返回的对象的proto指向了Foo的prototype上,这就是为啥上一个例子中:b.proto === Foo.prototype, 而a.proto === F.prototype 进而推导出a.proto === Foo. 4.委托机制: 由于原型链的存在,让我们可以查找到部署以当前对象,但是属于原型链上的方法或者属性,这样的行为可以称为行为委托,将方法或者属性委托到了原型上。