構造函數
//構造函數
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實例
。