工作原理
这里写的new操作原理并不是自己实验出来,而是在网上看了多个帖子得知的。
例子1:
function Student() {
}
const student1 = new Student()
const student2 = new Student()
console.log(student1)
const obj = new Object()
console.log(obj)
console.log(student1 === student2) //false
从这可以看到
new 出来的新对象,constructor会被指向构造
小结1:new操作符做了:创建了一个全新的对象(student1 != student2), 并且这个全新对象的_proto_会指向构建函数的prototype
例子2:
function Student(name) {
this.name = name
console.log(this)
}
function person(name) {
this.name = name
}
const student1 = new Student('xjj')
console.log(Student('zlp'))
可以看到
我们通过对比new和直接函数调用来对比this的指向问题。
可以看到通过直接的函数调用,this指向会遵循默认绑定(非严格模式下),绑定到全局对象window上。
而通过new操作构造调用,则会自动绑定到new期间创建的对象上,在这里是student1
小结2: new操作会绑定this到小结1那种新对象上
例子3:
function Student(name) {
this.name = name
return {
a: 'new' //不一定是object,可以是Functoin, Array, Date, RegExg, Error引用类型
}
}
function Person(name) {
this.name = name
return 'new' //不一定是字符串,是包括字符串的七种基本类型
}
const student1 = new Student('zlp')
const person1 = new Person('zlp')
console.log(student1) //{a: 'new'}
console.log(person1) // person{name: 'zlp'}
从这里我们可以看到,如果构造函数里面有返回的变量,如果变量是基本类型,则正常返回但如果是object类型都会被直接返回。
小结4:如果函数没有返回对象类型Object(包含Functoin, Array, Date, RegExg, Error),那么new表达式中的函数调用会自动返回this。
new操作总结:
- 创建全新的对象
- 该对象的_proto_会指向构造函数的原型prototype
- 将步骤1中创建的新对象作为this上下文
- 判断函数有没有返回对象类型的数据,(包含Functoin, Array, Date, RegExg, Error),那么new表达式中的函数调用会自动返回这个新的对象的this。
摘自MDN对new的解释
new模拟实现
按照上面的步骤,我们可以自己实现一个new操作:
function Student(name) {
this.name = name
}
const student1 = new Student('xjj')
function myNew(ctr, ...args) {
//1. 创建全新的对象
//2. 该对象的_proto_会指向构造函数的原型prototype
//3. 将步骤1中创建的新对象作为this上下文
//4. 判断函数有没有返回对象类型的数据,(包含Functoin, Array, Date, RegExg, Error),那么new表达式中的函数调用会自动返回这个新的对象的this。
//第一二步,Object.create(Parent.prototype)创建了一个空的对象,并且这个对象的__proto__属性是指向Parent.prototype的 。
const newObj = Object.create(ctr.prototype) //es6写法 性能更好
Object.setPrototypeOf(obj, Con.prototype) //es5以前的写法
//第三步,将这个对象作为this上下文,tips传参用args
const result = ctr.apply(newObj, args)
//第四步,判断函数有没有返回对象类型的数据
return result instanceof Object ? result : newObj
}
console.log(myNew(Student, 'xjj'))
console.log(student1)
结果: