一、关键字new做了什么
在面试中,我们常常会被问及new的作用,如下列代码:
const obj = new Base();
new实际上做了三步工作,以代码来说明:
const obj = {}; // 创建一个空对象
obj.__proto__ = Base.prototype; // 将空对象的__proto__指向构造函数的prototype属性
Base.call(obj); // 将构造函数的this指向obj,并调用构造函数
总结一下:
- 创建一个空对象
 - 将空对象的
__proto__属性指向构造函数的prototype - 将构造函数中的
this指向空对象并且调用构造函数 - 如果构造函数有返回对象,则
new返回这个对象,反之,则返回新创建的对象 
new创建的新对象可以:
- 访问到构造函数中的属性
 - 访问到构造函数原型链上的属性
 
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