js实现new
我们在使用new去创建构造函数的时候会经历四个步骤:
- 创建一个新对象
- 将构造函数的作用域赋值给新对象(因此this就指向了这个新对象)
- 执行构造函数中的代码(为这个新对象添加属性)
- 返回新对象
下面看一下代码实现:
function my_new(Super, ...args) {
const obj = {}
obj._proto_ = Super.prototype // 将 构造函数 的 原型对象 赋值给新建对象的 隐式原型
const result = Super.call(obj, ...args) // 执行 构造函数 并将 构造函数里面的this指向 新建对象obj
return typeof result === 'object' ? result : obj // 如果 执行结构是一个对象,那么就返回执行结果 否则返回新建对象
}
是不是很简单,下面做一道题来温习一下
function Fn(a) {
this.a= a
return {
a: 2,
b: 3,
}
}
Fn.prototype.a = 1
Fn.prototype.b = 2
Fn.prototype.c = 3
const fn = new Fn(4)
console.log(fn.a, fn.b, fn.c) // 最终会输出什么呢
答案就是:2,3,undefined
解析:实际上构造函数Fn返回的是一个新的对象,根据polyfill我们看到以返回对象优先,所以a,b输出2,3是没什么疑问的,而c不在返回的对象上,所以是undefined
function Fn(a) {
this.a= a
return ''
}
Fn.prototype.a = 1
Fn.prototype.b = 2
Fn.prototype.c = 3
const fn = new Fn(4)
console.log(fn.a, fn.b, fn.c) // 这回又会输出什么呢
答案是:4,2,3
解析:这回构造函数Fn返回了一个字符串,根据polyfill我们可以看出,当构造函数执行结果不是一个对象的时候,就返回的新创建的对象,新对象继承了构造函数的原型对象,所以a返回4,而构造函数在外部改变了原型对象上的属性,所以b,c返回2,3
最后我们看一个比较有意思的题
function Fn(a) {
this.a= a
return []
}
Fn.prototype.a = 1
Fn.prototype.b = 2
Fn.prototype.c = 3
const fn = new Fn(4)
console.log(fn.a, fn.b, fn.c) // 这个输出什么
答案是:三个undefined
解析:构造函数Fn返回一个数组,这个数组上没有a,b,c,所以都是undefined
好了,如果能不看答案就理解这三个题,就能很好的理解new的过程了
参考文章:
- 《JavaScript高级程序设计》
- https://juejin.im/post/6844903476766441479
作者:毛小星
本文版权归作者和博客园共有,欢迎转载,转载请标明出处