new方法做了什么事
要想实现new方法我们得先知道new方法做了什么事情?
在红宝书中的8.4.2节有提到new方法完成了什么事情。
使用new调用类的构造函数会执行如下操作:
(1) 在内存中创建一个新对象。
(2) 这个新对象内部的[[Prototype]]指针被赋值为构造函数的prototype属性。
(3) 构造函数内部的this被赋值为这个新对象(即this指向新对象)。
(4) 执行构造函数内部的代码(给新对象添加属性)。
(5) 如果构造函数返回非空对象,则返回该对象;否则,返回刚创建的新对象。
实现new方法
第一步很好理解,只需要创建一个对象就行了。
// Con为构造函数,用数组接收传来的参数
function mynew(Con, ...args) {
// 1.在内存中创建一个新对象。
let obj = {}
}
第二步,我们需要把新对象的原型指针指向构造函数的原型属性,而对象的原型指针不就是 __ proto__这个属性吗,第二步我们也可以完成
obj.__proto__ = Con.prototype // Con为传来的构造函数
第三步,要求我们改变this指向,第四步要求我们执行构造函数内部的代码,这两点我们可以用函数 apply 方法一块完成。
let res = Con.apply(obj, args)
第五步,判断函数执行结果的类型就可以了
if(res instanceof Object) {
return res
} else {
return obj
}
这五个步骤我们完成了,让我们来写在一起
function mynew(Con, ...args) {
// 1.在内存中创建一个新对象。
let obj = {}
// 2.这个新对象内部的[[Prototype]]指针被赋值为构造函数的prototype属性
obj.__proto__ = Con.prototype
// 3.构造函数内部的this被赋值为这个新对象(即this指向新对象)。
// 4.执行构造函数内部的代码(给新对象添加属性)。
let res = Con.apply(obj, args)
// 5.如果构造函数返回非空对象,则返回该对象;否则,返回刚创建的新对象。
if(res instanceof Object) {
return res
} else {
return obj
}
}
验证自己完成的new方法
function Person(name) {
this.name = name
}
Person.prototype.sayName = function() {
console.log("我的名字是" + this.name);
}
let p1 = myNew(Person, "wjk")
console.log(p1);
p1.sayName()
结果为: