构造函数
//构造函数
function Point(x,y){
this.x = x;
this.y = y;
}
var point = new Point(1,2);
console.log(point);// Point {x: 1, y: 2}
console.log(point.x,point.y);//输出 1 2
我们知道,构造函数和普通函数一样,唯一的区别是,构造函数是通过操作符new
来调用。
如果一不小心没有new
,直接当普通函数用了呢?
//普通函数
function Point(x,y){
this.x = x;
this.y = y;
}
var p = Point(3,4);
console.log(p);//输出 undefined
console.log(window.x,window.y);//输出 3 4
可以看到,Point(3,4)
返回的是undefined
,并不是预期的Point实例
,而且x
、y
被误添加到window对象
上了。
作用域安全的构造函数
呃,那有啥办法能避免这种不小心么?
有的,作用域安全的构造函数
,它能保证:不论你new
抑或不new
,都会返回一个新实例。
呃,作用域安全的构造函数 长啥样?
其实,我们有很多机会与它相遇。比如,new Vue(options)
,函数Vue
就是 作用域安全的构造函数。
function Vue (options) {
if (!(this instanceof Vue)
) {
warn('Vue is a constructor and should be called with the `new` keyword');
}
//...
}
又比如,http.createServer(options)
,函数Server
也是 作用域安全的构造函数。
function createServer(opts, requestListener) {
return new Server(opts, requestListener);
}
function Server(options, requestListener) {
if (!(this instanceof Server)) return new Server(options, requestListener);
//...
}
这种构造函数首先会甄别this
是不是当前类的一个实例,是,OK,继续往下走;不是,Sorry,先new
一个吧,然后才往下走。
照葫芦画瓢,我们把之前的例子改造一下。
function Point(x,y){
if(!(this instanceof Point)){
return new Point(x,y);
}
this.x = x;
this.y = y;
}
var point = new Point(1,2);
console.log(point);// 输出 Point {x: 1, y: 2}
console.log(point.x,point.y);// 输出 1 2
var p = Point(3,4);
console.log(p);// 输出 Point {x: 3, y: 4}
console.log(p.x,p.y);//输出 3 4
可以看到,不论是通过new
来调用,还是当作普通函数来使用,最后都会返回一个Point实例
。