new以及new的模拟实现 yinshibanxian

一、关键字new做了什么

在面试中,我们常常会被问及new的作用,如下列代码:

const obj = new Base();

new实际上做了三步工作,以代码来说明:

const obj = {}; // 创建一个空对象
obj.__proto__ = Base.prototype; // 将空对象的__proto__指向构造函数的prototype属性
Base.call(obj); // 将构造函数的this指向obj,并调用构造函数

总结一下:

  1. 创建一个空对象
  2. 将空对象的__proto__属性指向构造函数的prototype
  3. 将构造函数中的this指向空对象并且调用构造函数
  4. 如果构造函数有返回对象,则new返回这个对象,反之,则返回新创建的对象

new创建的新对象可以:

  1. 访问到构造函数中的属性
  2. 访问到构造函数原型链上的属性
function Person(name,age){
  this.name = name;
  this.age = age;
  
  this.sex = 'male';
}

Person.prototype.isHandsome = true;

Person.prototype.sayName = function(){
  console.log(`Hello , my name is ${this.name}`);
}

let handsomeBoy = new Person('Nealyang',25);

console.log(handsomeBoy.name) // Nealyang
console.log(handsomeBoy.sex) // male
console.log(handsomeBoy.isHandsome) // true

handsomeBoy.sayName(); // Hello , my name is Nealyang

二、模拟实现new

function objectFactory() {
    let obj = new Object(); // 创建一个空对象.
    Constructor = Array.prototype.shift.call(arguments); // 获取传入的第一个参数,即构造器
    const fNOP = function(){};
    fNOP.prototype = Constructor.prototype;
    obj = new fNOP(); 
    const ret = Constructor.apply(obj,arguments); // 构造函数的this指向obj并调用构造函数
    return typeof ret === 'object'? ret:obj; 
}
  • new Object()的方式新建一个对象obj
  • 取出第一个参数,就是我们要传入的构造函数,因为此处shift会修改原数组,所以arguments会去除第一个参数
  • obj的原型指向构造函数,这样obj就可以访问构造函数原型上的方法
  • 将构造函数的this指向obj,并执行构造函数,接受返回结果
  • 如果构造函数返回一个对象,那么返回这个对象,否则返回新建的对象

来测试一下

function Person(name,age){
  this.name = name;
  this.age = age;
  
  this.sex = 'male';
}

Person.prototype.isHandsome = true;

Person.prototype.sayName = function(){
  console.log(`Hello , my name is ${this.name}`);
}

function objectFactory() {
    let obj = new Object(); // 创建一个空对象
    Constructor = Array.prototype.shift.call(arguments); // 获取传入的第一个参数,即构造器
    const fNOP = function(){};
    fNOP.prototype = Constructor.prototype;
    obj = new fNOP(); 
    const ret = Constructor.apply(obj,arguments); // 构造函数的this指向obj并调用构造函数
    return typeof ret === 'object'? ret:obj; 
}

let handsomeBoy = objectFactory(Person,'Nealyang',25);

console.log(handsomeBoy.name) // Nealyang
console.log(handsomeBoy.sex) // male
console.log(handsomeBoy.isHandsome) // true

handsomeBoy.sayName(); // Hello , my name is Nealyang