提到“構(gòu)造函數(shù)”,大部分人會(huì)聯(lián)想到Java類的概念,JavaScript也有構(gòu)造函數(shù),其使用語(yǔ)法與Java或者其他基于類的語(yǔ)言中創(chuàng)建對(duì)象的語(yǔ)法相似。
JavaScript構(gòu)造函數(shù)是一類比較特殊的函數(shù),特點(diǎn)為:
- 用
new關(guān)鍵字調(diào)用函數(shù) - 函數(shù)首字母大寫(xiě)
面試中,我經(jīng)常針對(duì)構(gòu)造函數(shù)問(wèn)兩個(gè)問(wèn)題:
- 構(gòu)造函數(shù)首字母必須大寫(xiě)嗎?
- 不用
new關(guān)鍵字,直接運(yùn)行構(gòu)造函數(shù),是否會(huì)出錯(cuò)?如果不會(huì)出錯(cuò),那么,用new和不用new調(diào)用構(gòu)造函數(shù),有什么區(qū)別?
問(wèn)題1基本100%都能答對(duì)(大小寫(xiě)都可以),問(wèn)題2有20%同學(xué)會(huì)答錯(cuò),尤其是第二問(wèn)。
那么,讓我們看看new操作符到底起到什么作用?
1. 使用new操作符調(diào)用函數(shù)
例子:
function Person(name){
this.name = name;
this.say = function(){
return "I am " + this.name;
}
}
var person1 = new Person('nicole');
person1.say(); // "I am nicole"
用new調(diào)用構(gòu)造函數(shù),函數(shù)內(nèi)部會(huì)發(fā)生如下變化:
- 創(chuàng)建一個(gè)this變量,該變量指向一個(gè)空對(duì)象。并且該對(duì)象繼承函數(shù)的原型;
- 屬性和方法被加入到this引用的對(duì)象中;
- 隱式返回this對(duì)象(如果沒(méi)有顯性返回其他對(duì)象)
用偽程序來(lái)展示上述變化:
function Person(name){
// 創(chuàng)建this變量,指向空對(duì)象
var this = {};
// 屬性和方法被加入到this引用的對(duì)象中
this.name = name;
this.say = function(){
return "I am " + this.name;
}
// 返回this對(duì)象
return this;
}
可以看出,用new調(diào)用構(gòu)造函數(shù),最大特點(diǎn)為,this對(duì)象指向構(gòu)造函數(shù)生成的對(duì)象,所以,person1.say()會(huì)返回字符串: "I am nicole"。
小貼士
如果指定了返回對(duì)象,那么,this對(duì)象可能被丟失。
function Person(name){
this.name = name;
this.say = function(){
return "I am " + this.name;
}
var that = {};
that.name = "It is that!";
return that;
}
var person1 = new Person('nicole');
person1.name; // "It is that!"
2. 直接調(diào)用函數(shù)
如果直接調(diào)用函數(shù),那么,this對(duì)象指向window,并且,不會(huì)默認(rèn)返回任何對(duì)象(除非顯性聲明返回值)。
還是拿Person函數(shù)為例,直接調(diào)用Person函數(shù):
var person1 = Person('nicole');
person1; // undefined
window.name; // nicole
可見(jiàn),直接調(diào)用構(gòu)造函數(shù)的結(jié)果,并不是我們想要的。
3.小結(jié)
為了防止因?yàn)橥浭褂?code>new關(guān)鍵字而調(diào)用構(gòu)造函數(shù),可以加一些判斷條件強(qiáng)行調(diào)用new關(guān)鍵字,代碼如下:
function Person(name){
if (!(this instanceof Person)) {
return new Person(name);
}
this.name = name;
this.say = function(){
return "I am " + this.name;
}
}
var person1 = Person('nicole');
console.log(person1.say()); // I am nicole
var person2 = new Person('lisa');
console.log(person2.say()); // I am lisa