js中new操作符做了些什么及如何实现一个简单的new

122 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 2天,点击查看活动详情

我们经常使用new为一个构造函数创建一个他的实例对象,并且这个实例对象还可以使用构造函数的原型上的属性和方法。内部实现其实可以分为这四步:

  1. 创建一个空对象(最后一般会返回这个对象)
  2. 将创建的空对象的[[prototype]]属性指向构造函数的prototype(可以让实例对象访问到原型上的对象)
  3. 把构造函数的this绑定到新对象上(拿到构造函数的所有属性和方法)
  4. 最后判断构造函数是否返回了对象,如果返回对象则实例对象就是这个对象,反之实例对象是创建的新对象

写个例子帮助理解

const Mountain = function(){
  this.characteristic = 'tall';
  // return {}
}
Mountain.prototype.getHeight = function(){
  console.log(this.height);
}

const lushan = new Mountain();
lushan.height = '1474'

lushan.getHeight(); // 1474  验证第二步的空对象的`[[prototype]]`属性指向构造函数的`prototype`
console.log(lushan.characteristic); // tall  验证第三步构造函数的this绑定到新对象上
// console.log(lushan); // 构造函数返回对象 实例将无法使用任何构造函数的属性方法(包括原型上的)  验证第四步

简单实现一个new操作符

const mynew = function(constrc, ...args){
    // 创建一个对象并把构造函数的prototype属性挂载在对象的[[prototype]]上
    const obj = Object.create(constrc.prototype);
    // 第一步和第二步也可以这样写
    // const obj = {}
    // obj.__proto__ = constrc.prototype;
    
    // 把构造函数的this绑定到新对象上
    const result = constrc.apply(obj, args);
    
    // 判断构造函数是否返回一个对象
    return result instanceof Object ? result : obj;
}

测试

const fun = function(){
  this.a = '123';
  // return {}
}

fun.prototype.outputa = function(){
  console.log(this.a);
}

const obj = mynew(fun);

console.log(obj.a); // 123
obj.outputa(); // 123
console.log(obj.__proto__ === fun.prototype); // true

// console.log(obj); // {}   当构造函数返回一个对象

这样就基本实现了一个简单的new操作符。new操作符也是js中的一种继承。