在javascript中一共有四種調(diào)用模式:方法調(diào)用模式,函數(shù)調(diào)用模式,構(gòu)造器調(diào)用模式,apply調(diào)用模式
這些模式在如何初始化關(guān)鍵參數(shù)this上存在差異。
1 方法調(diào)用模式(也就是用"."的方式來(lái)調(diào)用的)
當(dāng)一個(gè)函數(shù)被保存為對(duì)象的一個(gè)屬性時(shí),我們稱它為一個(gè)方法。當(dāng)一個(gè)方法被調(diào)用時(shí),this被綁定到該對(duì)象。如果一個(gè)調(diào)用表達(dá)式包含一個(gè)屬性存取表達(dá)式(即一個(gè).點(diǎn)表達(dá)式或者[subscript]下標(biāo)表達(dá)式),那么它被當(dāng)做一個(gè)方法來(lái)調(diào)用
var myObject = {
value :0;
increment:fucntion (inc){
this.value += typeof inc ==='number' ? inc:1;
}
};
myObject.increment();
document.writeln(myObject.value); //1
myObject.increment(2);
document.writeln(myObject.value); //3
方法可以使用this去訪問(wèn)對(duì)象,所以它能從對(duì)象中取得或修改該對(duì)象。this到對(duì)象的綁定發(fā)生在調(diào)用的時(shí)候。這個(gè)“超級(jí)”遲綁定( very late binding)使得函數(shù)可以對(duì)this高度復(fù)用。通過(guò)this可取得它們所屬對(duì)象的上下文的方法稱為公共方法。
2 函數(shù)調(diào)用模式
當(dāng)一個(gè)函數(shù)并非一個(gè)對(duì)象的屬性是,那么它被當(dāng)做一個(gè)函數(shù)來(lái)調(diào)用:
var sum = add(3,4); //sum的值為7
當(dāng)函數(shù)以此模式調(diào)用時(shí),this被綁定到全局對(duì)象。這是語(yǔ)言設(shè)計(jì)上的一個(gè)錯(cuò)誤,倘若語(yǔ)言設(shè)計(jì)正確,當(dāng)內(nèi)部函數(shù)被調(diào)用時(shí),this應(yīng)該仍然綁定到外部函數(shù)的this變量。這個(gè)設(shè)計(jì)錯(cuò)誤錯(cuò)誤的后果是方法不能利用內(nèi)部函數(shù)來(lái)幫助它工作,因?yàn)閮?nèi)部函數(shù)的this被綁定了錯(cuò)誤的值,所以不能共享該方法對(duì)對(duì)象的訪問(wèn)權(quán)。幸運(yùn)的是,有一個(gè)很容易的解決方案:如果該方法定義一個(gè)變量并給他賦值為this,那么內(nèi)部函數(shù)就可以通過(guò)那個(gè)變量訪問(wèn)到this。
//給myObject增加一個(gè)double方法
myObject.double = function(){
var that = this; //解決方案
var helper = function(){
that.value = add(that.value,that.value);
};
helper();//以函數(shù)的形式調(diào)用helper
};
//以方法的形式調(diào)用double
myObject.double();
document.writeln(myObject.getValue()); //6
3、構(gòu)造器調(diào)用模式:
調(diào)用形式:在函數(shù)名前加 new 來(lái)調(diào)用。
this綁定:將創(chuàng)建一個(gè)隱藏連接到該函數(shù)的 prototype 成員的新對(duì)象,同時(shí) this 將會(huì)被綁定到這個(gè)新對(duì)象上。
例子:
// 創(chuàng)建一個(gè)名為 Quo 的構(gòu)造器函數(shù)。它構(gòu)造一個(gè)帶有 status 屬性的對(duì)象。
var Quo = function (string) {
this.status = string;
};
// 給 Quo 的所有實(shí)例提供一個(gè)名為 get_status 的公共方法
Quo.prototype.get_status = function () {
return this.status;
};
注意:在JavaScript中如果用 new 方式調(diào)用一個(gè)函數(shù),如果函數(shù)沒(méi)有返回一個(gè)對(duì)象,則返回 this。
下面在用 new 調(diào)用 Quo 這個(gè)構(gòu)造函數(shù)時(shí),因?yàn)?Quo 函數(shù)沒(méi)有返回值,所以默認(rèn)返回 this gei myQuo。
// 構(gòu)造一個(gè) Quo 實(shí)例
var yQuo = new Quo("confused"); // myQuo 的值被賦予了 this,而此時(shí)的 this 是 Quo 的 prototype 成員。
document.writeln(myQuo.get_status()); // confused this.status 即 Quo.prototype.status 在調(diào)用 new 構(gòu)造 Quo 時(shí)即被賦予了 confused。
document.writeln(myQuo.status); // confused
如果調(diào)用構(gòu)造器函數(shù)時(shí)前面沒(méi)有加 new,將會(huì)發(fā)生錯(cuò)誤:
var myQuo = Quo("confused");
document.writeln(myQuo); // undefined 可見(jiàn),沒(méi)有用 new 調(diào)用構(gòu)造器函數(shù),它將不會(huì)有任何返回值給 myQuo。
4、Apply/Call調(diào)用模式:
調(diào)用形式:通過(guò)apply/call方法調(diào)用函數(shù),其中第一個(gè)參數(shù)為我們指定的 this 的值。
this綁定:允許我們選擇 this 的值。
例子:
// 構(gòu)造一個(gè)包含兩個(gè)數(shù)字的數(shù)組,通過(guò)apply方法調(diào)用前面的add函數(shù),將數(shù)組中的數(shù)字相加
var array = [3, 4];
var sum = add.apply(null, array); // sum的值為7。add()中沒(méi)有使用到 this 所以參數(shù)給其設(shè)為 null 即可。
例子:
// 構(gòu)造一個(gè)包含 status 成員的對(duì)象,通過(guò) apply 方法調(diào)用前面的 Quo對(duì)象的get_status 方法返回 status。
var statusObject = {
status : 'A-OK'
};
var status = Quo.prototype.get_status.apply(statusObject); // status 值為'A-OK' 在通過(guò) apply 調(diào)用 Quo 的 get_status 方法時(shí)將 statusObject 對(duì)象綁定給了 this ,所以 get_status 方法返回的結(jié)果是 statusObject 的 status 屬性。