要手动实现一个 new
操作符,首先要知道 new
操作符都做了什么事,即构造函数的内部原理:
1.创建一个新对象;
2.链接到原型(将构造函数的 prototype
赋值给新对象的 __proto__
);
3.绑定this(构造函数中的this指向新对象并且调用构造函数)
4.返回新对象
这样我们就可以手动实现一个 new
方法了
function realizeNew () {
//创建一个新对象
let obj = {};
//获得构造函数
let Con = [].shift.call(arguments);
//链接到原型(给obj这个新生对象的原型指向它的构造函数的原型)
obj.__proto__ = Con.prototype;
//绑定this
let result = Con.apply(obj,arguments);
//确保new出来的是一个对象
return typeof result === "object" ? result : obj
}
我们实现的 realizeNew()
方法需要传入的参数是:构造函数 + 属性
首先我们创建一个新对象,
然后通过 arguments
类数组我们可以知道参数中包含了构造函数以及我们调用create时传入的其他参数,接下来就是要想如何得到其中这个构造函数和其他的参数,由于arguments是类数组,没有直接的方法可以供其使用,我们可以有以下两种方法:
1.Array.from(arguments).shift()
; 转换成数组 使用数组的方法 shift
将第一项弹出
2.[].shift().call(arguments)
; 通过 call()
让arguments
能够借用shift()
方法
绑定this的时候需要注意:
1.给构造函数传入属性,注意构造函数的this属性
2.参数传进 Con
对 obj
的属性赋值,this要指向 obj
对象
3.在 Con
内部手动指定函数执行时的this 使用call、apply
实现
最后我们需要返回一个对象
我们来测试一下:
function Person (name,age){
this.name = name;
this.age = age;
this.say = function () {
console.log("I am " + this.name)
}
}
//通过new创建构造实例
let person1 = new Person("Curry",18);
console.log(person1.name); //"Curry"
console.log(person1.age); //18
person1.say(); //"I am Curry'
//通过realize()方法创造实例
let person2 = realizeNew (Person,"Curry",18);
console.log(person2.name); //"Curry"
console.log(person2.age); //18
person2.say(); //"I am Curry'
网友评论