jtwang7 / JavaScript-Note

JavaScript学习笔记
10 stars 2 forks source link

JS 基础篇 - new 操作符 #50

Open jtwang7 opened 3 years ago

jtwang7 commented 3 years ago

参考文章:

new 操作符的作用

new 运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例。———— 摘自《MDN Web Docs》

简单理解,new 操作符会基于一个对象模版或构造函数,创建出一个对象实例。其中:

  1. new 创建的实例可以访问构造函数中的属性
  2. new 创建的实例可以访问构造函数原型中的属性, new 将实例和构造函数通过原型链连接
  3. 构造函数返回原始值, 返回值不会生效; 构造函数返回对象, 该对象有效, 返回对象会导致 new 操作符不起作用(new 操作符本质上返回了该构造函数的 this 对象)

new 操作符的原理及实现

实现步骤

  1. 创建一个新的对象;
  2. 将该对象连接到构造函数的原型链上(使新对象可以调用构造函数原型链上的属性和方法);
  3. 利用 callapply 强绑定构造函数的 this 指向,并执行构造函数,在新对象上挂载构造函数内部定义的属性和方法 (使新对象可以调用构造函数自身定义的属性和方法);
  4. 判断构造函数的返回值类型,返回最终结果:
    • 若构造函数返回原始类型,则忽略该返回值,并返回当前创建的实例对象
    • 若构造函数返回引用类型,则返回这个引用类型的对象,忽略创建的实例
    • 若构造函数没有显式返回值,默认返回的是构造函数的 this 对象,实际上就是构造函数的实例对象,和当前创建的实例对象本质上一致
function myNew (Fn, ...args) {
  // 步骤一
  const _this = {};

  // 步骤二
  Reflect.setPrototypeOf(_this, Fn); // this.__proto__ = Fn.prototype;

  // 步骤三
  const res = Fn.apply(_this, args);

  // 步骤四
  return (res instanceof Object) ? res : _this;
}

调用 Object.create() 的实现步骤

Object.create() 合并了创建对象和连接构造函数原型链的操作

function _new(Fn, ...args) {
  let _this = Object.create(Fn.prototype); // Object.create() 基于 Fn.prototype 原型创建空对象
  let obj = Fn.apply(_this, args); // 基于 _this 空对象立即执行 Fn , 在 _this 上挂载 args 参数. Fn 可能有返回值, 创建一个 obj 变量接收
  return obj instanceof Object ? obj : _this // 若返回值为对象, 则返回该对象, 否则返回 _this 对象, 这样就忽略了原始值
}