Open DeanTG opened 1 year ago
/**
* 方法一 (推荐)
*
* 工厂方法实现 new
* objectFactory(constructor, ...restParams)
*/
function myNew1() {
// 创建一个新对象 从 Object.prototype 上克隆一个对象
let obj = new Object();
// 取出第一个参数,就是我们要传入的构造函数。此外因为 shift 会修改原数组,所以 arguments 会被去除第一个参数
// 使 new 出的对象 可以访问构造函数及其原型对象上的的属性和方法
// 取出构造函数,从 arguments 对象 中取出第一个参数即为构造函数
let con = Array.prototype.shift.call(arguments);
// 将 obj 的原型指向构造函数,这样 obj 就可以访问到构造函数原型中的属性
// 将 new 出的对象原型 指向 构造函数的原型对象 这样 obj 就可以访问到构造函数原型中的属性
// 执行构造函数,并改变 new 出的对象的 this, 这样 obj 就可以访问到构造函数中的属性
// 区别:
// 一个能访问的构造函数原型上的属性和方法 - 原型链
// 一个能访问到构造函数本身上的属性和方法 - 借助 apply 改变 this 指向
obj.__proto__ = con.prototype;
// 绑定this,执行构造函数,使用 apply 借用构造函数,改变构造函数 this 的指向到新建的对象,这样 obj 就可以访问到构造函数中的属性
// 执行并返回结果,arguments 数组经过上面 shift 的处理已经只剩下参数了,shift 可改变原数组 arguments
let result = con.apply(obj, arguments);
// 确保 new 出来的是个对象
// 如果构造函数返回值是引用类型,则返回构造函数的返回值。构造函数返回了一个对象,在实例 中只能访问返回的对象中的属性
// 如果构造函数的返回值是基本类型,则返回新创建的对象。尽管有返回值,但是相当于没有返回值进行处理。
// 所以我们还需要判断返回的值是不是一个对象,如果是一个对象,我们就返回这个对象,如果没有,我们该返回什么就返回什么
// 返回值处理
// 当构造函数的返回值是基本类型时,不做处理,返回obj
// 当构造函数的返回值是引用类型时,返回结果
return typeof result === "object" ? result : obj;
}
new 一个对象发生了什么
(1)创建一个新的对象(创建一个新的对象) (2)设置这个新对象的原型为构造函数的原型(设置对象的原型属性) (3)执行构造函数,设置构造函数的 this 指向为新创建的对象,执行构造函数中定义的行为。(确定 this 指向) (4)返回值处理 如果构造函数返回值是引用类型,则返回构造函数的返回值。构造函数返回了一个对象,在实例中只能访问返回的对象中的属性 如果构造函数的返回值是基本类型,则返回新创建的对象。尽管有返回值,但是相当于没有返回值进行处理。