一、new 做了什么?
(1) 创建一个新对象;
(2) 将构造函数的作用域赋给新对象(因此 this 就指向了这个新对象) ;
(3) 执行构造函数中的代码(为这个新对象添加属性) ;
(4) 返回新对象。
二、如何实现
// 方法一
function myNew() {
// 通过arguments类数组打印出的结果,我们可以看到其中包含了构造函数以及我们调用objectfactory时传入的其他参数
// 接下来就是要想如何得到其中这个构造函数和其他的参数
// 由于arguments是类数组,没有直接的方法可以供其使用,我们可以有以下两种方法:
// 1. Array.from(arguments).shift(); //转换成数组 使用数组的方法shift将第一项弹出
// 2.[].shift().call(arguments); // 通过call() 让arguments能够借用shift方法
const Constructor = [].shift.call(arguments);
const args = arguments;
// 新建一个空对象 纯洁无邪
let obj = new Object();
// 接下来的想法 给obj这个新生对象的原型指向它的构造函数的原型
// 给构造函数传入属性,注意:构造函数的this属性
// 参数传进Constructor对obj的属性赋值,this要指向obj对象
// 在Coustructor内部手动指定函数执行时的this 使用call、apply实现
Constructor.call(obj, ...args);
return obj;
}
// 方法二
function createNew() {
//创建一个空对象
let obj = new Object();
//获取构造函数
let Constructor = [].shift.call(arguments);
//链接到原型
obj.__proto__ = Constructor.prototype;
//绑定this值
let result = Constructor.apply(obj, arguments); //使用apply,将构造函数中的this指向新对象,这样新对象就可以访问构造函数中的属性和方法
//返回新对象
return typeof result === "object" ? result : obj; //如果返回值是一个对象就返回该对象,否则返回构造函数的一个实例对象
}
三、测试实例
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'
//通过 myNew() 方法创造实例
let person2 = myNew(Person, "Curry", 18);
console.log(person2.name); //"Curry"
console.log(person2.age); //18
person2.say(); //"I am Curry'
//通过 createNew() 方法创造实例
let person3 = createNew(Person, "Curry", 18);
console.log(person3.name); //"Curry"
console.log(person3.age); //18
person3.say(); //"I am Curry'