1. 初识new
new运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例。
function Car(make, model, year) {
this.make = make;
this.model = model;
this.year = year;
}
const car1 = new Car('Eagle', 'Talon TSi', 1993);
console.log(car1.make);
// "Eagle"
2. new的实现
new
关键字会在这段代码中发挥什么作用呢?
- 第一步:创建一个空的简单JavaScript对象(即{});
- 第二步:为步骤1新创建的对象添加属性__proto__,将该属性链接至构造函数的原型对象 ;
- 第三步:将步骤1新创建的对象作为this的上下文 ;
- 第四步:如果该函数没有返回对象,则返回this。
我们结合代码来理解上文new Car
的过程:
//第一步:
var obj = {}
//第二步:
obj.__proto__ = Car.prototype
//第三步:
Car.call(obj,'Eagle', 'Talon TSi', 1993)
//第四步:
return obj
这里需要注意的是,此时的Car构造函数没有返回值,这也是我们推崇的情况,构造函数的目的是为了帮助用户快速构建对象,为了代码的可读性和可维护性,建议不要掺杂除构造作用外的代码,同样的,一般的功能函数也不要作为构造函数。
但是,如果此时的Car存在返回值呢?比如:
function Car(make, model, year) {
this.make = make;
this.model = model;
this.year = year;
return {
make:'Benz',
model:'Pickup Truck',
year:1995
}
}
const car1 = new Car('Eagle', 'Talon TSi', 1993);
console.log(car1);
输出:
{ make: 'Benz', model: 'Pickup Truck', year: 1995 }
这时候,因为构造函数主动返回了一个对象,所以覆盖了正常的对象创建步骤。注意: 这里必须返回一个对象才会覆盖,若返回一个简单变量(如字符串),就不会覆盖:
function Car(make, model, year) {
this.make = make;
this.model = model;
this.year = year;
return 'A new car'
}
const car1 = new Car('Eagle', 'Talon TSi', 1993);
console.log(car1);
输出:
Car { make: 'Eagle', model: 'Talon TSi', year: 1994 }
3. 增加属性
随着时间,之前的Car构造函数中仅有的三个属性已经不能满足当前的需求,比如我们需要增加一个color属性,表示这一辆车的颜色。
可以直接使用car1.color='red'
语句给car1增加color
属性:
car1.color = 'red'
console.log(car1);
输出:
Car { make: 'Eagle', model: 'Talon TSi', year: 1994, color: 'red' }
但是,如果我们需要给每一辆车都增加这一属性,该怎么做呢?
给每一辆车都按照这样的语句来添加属性?
这时候,我们可以使用Function.prototype
属性将color属性添加到该对象类型的定义之中。
Car.prototype.color = "default color"
console.log(car1.color);
4. 结语
关于JavaScript 对象的六种创建方式可以查看笔者的这一篇文章【草稿ing】。