基本用法
new
命令的作用,就是执行构造函数,返回一个实例对象。
new
命令本身就可以执行构造函数,所以后面的构造函数可以带括号,也可以不带括号。
csharp
// 推荐的写法
var v = new Vehicle();
// 不推荐的写法
var v = new Vehicle;
问题:如果忘了使用 new 命令,直接调用构造函数会发生什么?
答:这种情况下,构造函数就变成了普通函数,并不会生成实例对象。且 this 这时代表全局对象。
ini
var Vehicle = function (){
this.price = 1000;
};
var v = Vehicle();
v // undefined
price // 1000
为了保证构造函数必须与 new 命令一起使用,解决方法是:构造函数内部使用严格模式,即第一行加上 use strict。
另一个解决方法,构造函数内部判断是否使用 new 命令,如果发现没有使用,则直接返回一个实例对象。
javascript
function Fubar(foo, bar) {
if (!(this instanceof Fubar)) {
return new Fubar(foo, bar);
}
this._foo = foo;
this._bar = bar;
}
Fubar(1, 2)._foo // 1
(new Fubar(1, 2))._foo // 1
new 命令的原理
使用 new 命令时,它后面的函数依次执行下面的步骤。
-
创建一个空对象,作为将要返回的对象实例。
-
将这个空对象的原型( proto )指向构造函数的 prototype 属性
-
将构造函数内部的 this 绑定到新创建的空对象上。
-
执行构造函数:将构造函数作为函数调用,传递给新对象以及其他参数。
-
如果构造函数返回的是一个对象,则返回该对象;否则,返回新创建的对象。
也就是说,构造函数内部,this 指的是一个新生成的空对象,所有针对 this 的操作,都会发生在这个空对象上。
new
命令简化的内部流程,可以用下面的代码表示。
javascript
// 构造函数
var Person = function (name, age) {
this.name = name;
this.age = age
}
function _new(constructor, ...params) {
// 创建一个新对象,且原型指向构造函数的原型
var context = Object.create(constructor.prototype);
// 执行构造函数
var result = constructor.apply(context, params);
// 如果返回结果是对象,就直接返回。否则返回 context 对象
return result instanceof Object ? result : context;
}
// 实例
var actor = _new(Person, '张三', 28);