共计 1775 个字符,预计需要花费 5 分钟才能阅读完成。
前言
JS 中有一种说法,叫做一切皆为对象。对象是什么呢?大话来讲,对象是一种容器,里面封装了属性和方法。在每天编程中,最基本的事情也是频繁的干的事情就是创建一个对象,然后使用它干各种各样的事情。创建对象的方法有构造函数创建、语法糖创建、还有 new
命令创建。当然,本文的标题已经表明这次的主角是 new
关键字了。
new 的基本用法
new
命令的作用,就是执行构造函数,返回一个实例对象。
ps: 如果忘了使用 new 命令,构造函数就变成了普通函数,并不会生成实例对象。
// 1、不带参数情况 | |
var Vehicle = function () {this.price = 1000;}; | |
var v = new Vehicle(); | |
v.price // 1000 | |
// 2、带参数情况 | |
var Vehicle = function (p) {this.price = p;}; | |
var v = new Vehicle(500); |
当然,为了保证构造函数必须与 new
命令一起使用两种方法。
方法一:
构造函数内部使用严格模式,即第一行加上 use strict
。这样的话,一旦忘了使用new
命令,直接调用构造函数就会报错。
function Fubar(foo, bar){ | |
'use strict'; | |
this._foo = foo; | |
this._bar = bar; | |
} | |
Fubar() | |
// TypeError: Cannot set property '_foo' of undefined |
方法二:
构造函数内部判断是否使用 new
命令,如果发现没有使用,则直接返回一个实例对象。
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
命令时,会发生什么。
1、创建一个空对象,作为将要返回的对象实例。
2、将这个空对象的原型,指向构造函数的 prototype
属性。
3、将这个空对象赋值给函数内部的 this
关键字。
4、开始执行构造函数内部的代码。
从上面步骤可以看出,其构造函数内部,通过 this
指的就是新生对象。
如果你对 this
不是很清楚,可以看我的另一篇文章
关于 this、call、applay 和 bind。
注意:如果构造函数内部有 return 语句,而且 return 后面跟着一个对象,new 命令会返回 return 语句指定的对象;否则,就会不管 return 语句,返回 this 对象。
例子 1
var Vehicle = function () { | |
this.price = 1000; | |
return 1000; | |
}; | |
(new Vehicle()) === 1000 | |
// false |
例子 2
var Vehicle = function (){ | |
this.price = 1000; | |
return {price: 2000}; | |
}; | |
(new Vehicle()).price | |
// 2000 |
另一方面,如果对普通函数(内部没有 this
关键字的函数)使用 new
命令,则会返回一个空对象。
function getMessage() {return 'this is a message';} | |
var msg = new getMessage(); | |
msg // {} | |
typeof msg // "object" |
new 关键字的内部流程
function _new(/* 构造函数 */ constructor, /* 构造函数参数 */ params) { | |
// 将 arguments 对象转为数组 | |
var args = [].slice.call(arguments); | |
// 取出构造函数 | |
var constructor = args.shift(); | |
// 创建一个空对象,继承构造函数的 prototype 属性 | |
var context = Object.create(constructor.prototype); | |
// 执行构造函数 | |
var result = constructor.apply(context, args); | |
// 如果返回结果是对象,就直接返回,否则返回 context 对象 | |
return (typeof result === 'object' && result != null) ? result : context; | |
} | |
// 实例 | |
var actor = _new(Person, '张三', 28); |