A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 天树123 中级黑马   /  2020-4-15 10:35  /  1021 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

一、new操作背后
new 运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例。new 关键字会进行如下的操作:
1、创建一个空的简单JavaScript对象(即{});
2、链接该对象(即设置该对象的构造函数)到另一个对象 ;
3、将步骤1新创建的对象作为this的上下文 ;
4、如果该函数没有返回对象,则返回this

以上是 MDN 的原文,通过上面描述,我们能比较清晰的了解到一个简单new运算符背后做了些什么。现在我们来看看下面这段代码:
function Car(make, model, year) {
  this.make = make;
  this.model = model;
  this.year = year;
}

Car.prototype={
  getMake: function() {
    return this.make
  }
}

var car = new Car('Eagle', 'Talon TSi', 1993)
我们来分解一下 var car = new Car('Eagle', 'Talon TSi', 1993)这行代码
1:创建一个简单空对象
var obj = {}
2:链接该对象到另一个对象(原型链)
// 设置原型链
obj.__proto__ = Car.prototype
3:将步骤1新创建的对象作为 this 的上下文
// this指向obj对象
Car.apply(obj, ['Eagle', 'Talon TSi', 1993])
4:如果该函数没有返回对象,则返回this
// 因为 Car() 没有返回值,所以返回obj
var car = obj
car.getMake() // 'Eagle'
需要注意的是如果 Car() 有 return 则返回 return的值
var rtnObj = {}
function Car(make, model, year) {
  // todo
  // ...
  //返回一个对象
  return rtnObj
}

var car = new Car('Eagle', 'Talon TSi', 1993)
console.log(car === rtnObj) // true

二、封装一个方法
现在我们把上面的步骤封装成一个对象实例化方法
function objectFactory(){
    var obj = {};
    //取得该方法的第一个参数(并删除第一个参数),该参数是构造函数
    var Constructor = [].shift.apply(arguments);
    //将新对象的内部属性__proto__指向构造函数的原型,这样新对象就可以访问原型中的属性和方法
    obj.__proto__ = Constructor.prototype;
    //取得构造函数的返回值
    var ret = Constructor.apply(obj, arguments);
    //如果返回值是一个对象就返回该对象,否则返回构造函数的一个实例对象
    return typeof ret === "object" ? ret : obj;
}

三、class
es6 中新增加了关键字 class ,如果把上面 function 换成 class 结果会怎样呢?其实结果是一样的。
class Car {
  constructor(make, model, year) {
    this.make = make;
    this.model = model;
    this.year = year;
  }
  getMake() {
    return this.make
  }
}

var car = objectFactory(Car, 'Eagle', 'Talon TSi', 1993)
car.getMake() // 'Eagle'

四、小结
现在你明白 js 中 new 一个实例要做哪些操作了吗?看似简单的一个运算符,背后实现起来并没有那么简单,需要细细品味才得要义。

0 个回复

您需要登录后才可以回帖 登录 | 加入黑马