# new 的过程

使用 new 调用构造函数:new 的大致过程为:

  • 创建一个空的简单 JavaScript 对象(即 {} ),且其原型对象为构造函数的原型对象
  • 将步骤 1 新创建的对象作为构造函数的上下文 this ,执行后得到返回值
  • 如果该函数没有返回引用类型的值(null 除外),则返回 this,否则返回该引用类型的值。
function myNew(...args) {
  // 1.获取构造函数
  const constructor = args.shift();
  // 2.创建空对象并设置原型
  const obj = Object.create(constructor.prototype);
  // 3.绑定this并执行构造函数
  const result = constructor.apply(obj, args);
  // 4.返回构造函数显示返回的值或新对象
  return isObject(result) ? result : obj;
}
function isObject(obj) {
  return obj !== null && typeof obj === 'object';
}

new 调用构造函数时,如果构造函数返回了引用类型的值,则 new 会返回这个引用类型的值。

// 引用类型
function constr() {
  this.name = 'constr';
}
var instance = new constr();

function constr1() {
  this.name = 'constr1';
  return { name: 'another object name' };
}
var instance1 = new constr1();

function constr2() {
  this.name = 'constr2';
  return [1, 2, 3];
}
var instance2 = new constr2();

function constr3() {
  this.name = 'constr3';
  return new Set([1, 2, 3]);
}
var instance3 = new constr3();

function constr4() {
  this.name = 'constr4';
  return new WeakSet();
}
var instance4 = new constr4();

function constr5() {
  this.name = 'constr5';
  return new Map();
}
var instance5 = new constr5();

function constr6() {
  this.name = 'constr6';
  return new WeakMap();
}
var instance6 = new constr6();

function constr7() {
  this.name = 'constr7';
  return new Date();
}
var instance7 = new constr7();

function constr8() {
  this.name = 'constr8';
  return new RegExp();
}
var instance8 = new constr8();

function constr9() {
  this.name = 'constr9';
  return function foo() {};
}
var instance9 = new constr9();

function constr10() {
  this.name = 'constr10';
  return new String('some text');
}
var instance10 = new constr10();

function constr11() {
  this.name = 'constr11';
  return new Number('123');
}
var instance11 = new constr11();

function constr12() {
  this.name = 'constr12';
  return new Boolean(false);
}
var instance12 = new constr12();

function constr13() {
  this.name = 'constr13';
  return Math;
}
var instance13 = new constr13();

// 基本类型
function constr14() {
  this.name = 'constr14';
  return null;
}
var instance14 = new constr14();

function constr15() {
  this.name = 'constr15';
  return undefined;
}
var instance15 = new constr15();

function constr16() {
  this.name = 'constr16';
  return true;
}
var instance16 = new constr16();

function constr17() {
  this.name = 'constr17';
  return false;
}
var instance17 = new constr17();

function constr18() {
  this.name = 'constr18';
  return 123;
}
var instance18 = new constr18();

function constr19() {
  this.name = 'constr19';
  return NaN;
}
var instance19 = new constr19();

function constr20() {
  this.name = 'constr20';
  return '456';
}
var instance20 = new constr20();

function constr21() {
  this.name = 'constr21';
  return Symbol('foo');
}
var instance21 = new constr21();

function constr22() {
  this.name = 'constr22';
  return 123n;
}
var instance22 = new constr22();

console.log('instance', instance); // {name: "constr"}
console.log('instance1', instance1); // {name: "another object name"}
console.log('instance2', instance2); // [1, 2, 3]
console.log('instance3', instance3); // Set(3) {1, 2, 3}
console.log('instance4', instance4); // WeakSet {}
console.log('instance5', instance5); // Map(0) {}
console.log('instance6', instance6); // WeakMap {}
console.log('instance7', instance7); // Mon Mar 29 2021 15:44:20 GMT+0800 (中国标准时间)
console.log('instance8', instance8); // /(?:)/
console.log('instance9', instance9); // ƒ foo() {}
console.log('instance10', instance10); // String {"some text"}
console.log('instance11', instance11); // Number {123}
console.log('instance12', instance12); // Boolean {false}
console.log('instance13', instance13); // Math
console.log('instance14', instance14); // {name: "constr14"}
console.log('instance15', instance15); // {name: "constr15"}
console.log('instance16', instance16); // {name: "constr16"}
console.log('instance17', instance17); // {name: "constr17"}
console.log('instance18', instance18); // {name: "constr18"}
console.log('instance19', instance19); // {name: "constr19"}
console.log('instance20', instance20); // {name: "constr20"}
console.log('instance21', instance21); // {name: "constr21"}
console.log('instance22', instance22); // {name: "constr22"}