apply()和call()的真正用武之地是能夠擴(kuò)充函數(shù)來一運(yùn)行的作用域,如果我們相用傳統(tǒng)方法實(shí)現(xiàn)
1、每個(gè)函數(shù)都包含兩個(gè)非繼承而來的方法:apply()和call()。2、他們的用途相同,都是在特定的作用域中調(diào)用函數(shù)。3、接收參數(shù)方面不同,apply()接收兩個(gè)參數(shù),一個(gè)是函數(shù)運(yùn)行的作用域(this),另一個(gè)是參數(shù)數(shù)組。call()方法第一個(gè)參數(shù)與apply()方法相同,但傳遞給函數(shù)的參數(shù)必須列舉出來。
window.firstName = "diz";window.lastName = "song";
var myObject = {
firstName: "my", lastName: "Object"
};
function HelloName() {
console.log("Hello " + this.firstName + " " + this.lastName, " glad to meet you!");
}
HelloName.call(window); //或 .call(this);
HelloName.call(myObject);
運(yùn)行結(jié)果為:Hello diz song glad to meet you!Hello my Object glad to meet you!
例2
function sum(num1, num2) { return num1 + num2;}console.log(sum.call(window, 10, 10)); //20console.log(sum.apply(window,[10,20])); //30
分析:在例1中,我們發(fā)現(xiàn)apply()和call()的真正用武之地是能夠擴(kuò)充函數(shù)賴以運(yùn)行的作用域,如果我們想用傳統(tǒng)的方法實(shí)現(xiàn),請(qǐng)見下面的代碼:
window.firstName = "diz";window.lastName = "song";var myObject = { firstName: "my", lastName: "Object" };function HelloName() { console.log("Hello " + this.firstName + " " + this.lastName, " glad to meet you!");}HelloName(); //Hello diz song glad to meet you!myObject.HelloName = HelloName;myObject.HelloName(); //Hello my Object glad to meet you!
見加紅的代碼,我們發(fā)現(xiàn),要想讓HelloName()函數(shù)的作用域在對(duì)象myObject上,我們需要?jiǎng)討B(tài)創(chuàng)建myObject的HelloName屬性,此屬性作為指針指向HelloName()函數(shù),這樣,當(dāng)我們調(diào)用myObject.HelloName()時(shí),
函數(shù)內(nèi)部的this變量就指向myObjecct,也就可以調(diào)用該對(duì)象的內(nèi)部其他公共屬性了。通過分析例2,我們可以看到call()和apply()函數(shù)的真正運(yùn)用之處,在實(shí)際項(xiàng)目中,還需要根據(jù)實(shí)際靈活加以處理!一個(gè)小問題:再看一看函數(shù)中定義函數(shù)時(shí),this變量的情況
function temp1() { console.log(this); //Object {} function temp2() { console.log(this); //Window} temp2();}var Obj = {};temp1.call(Obj); //運(yùn)行結(jié)果見上面綠色的注釋
執(zhí)行結(jié)果與下面的相同:
function temp1() { console.log(this); temp2();} function temp2() { console.log(this);}var Obj = {};temp1.call(Obj);
call方法:調(diào)用一個(gè)對(duì)象的一個(gè)方法,以另一個(gè)對(duì)象替代當(dāng)前對(duì)象
call([thisObj[,arg1[, arg2[, [,.argN]]]]]) 參數(shù):thisObj 可選項(xiàng):將被用作當(dāng)前對(duì)象的對(duì)象 arg1 arg2 argN
call方法可以用來代替另一個(gè)方法調(diào)用一個(gè)方法。call方法可以將一個(gè)函數(shù)的對(duì)象從初始的上下文改變?yōu)橛蓆hisObj制定的新對(duì)象
如果沒有提供thisObj參數(shù),那么Global對(duì)象將被用作thisObj
obj1.method1.call(obj2,argument1,argument2);
call 的作用就是把obj1的方法放到obj2上使用,然后把a(bǔ)rguments1這些作為參數(shù)傳入(把作用于obj1上的方法轉(zhuǎn)移作用到obj2)
表面原因就是我們定義對(duì)象使用對(duì)象的字面表示法,字面表示法在簡(jiǎn)單的表示里我們很容易知道this指向?qū)ο蟊旧?,但是這個(gè)對(duì)象會(huì)有方法,方法的參數(shù)可能會(huì)是函數(shù),
而這個(gè)函數(shù)的定義里也可能會(huì)使用this指針,如果傳入的函數(shù)沒有被實(shí)例化過和被實(shí)例化過,this的指向是不同,
有時(shí)我們還想在傳入函數(shù)里通過this指向外部函數(shù)或者指向被定義對(duì)象本身,這些亂七八糟的情況使用交織在一起導(dǎo)致this變得很復(fù)雜,結(jié)果就變得糊里糊涂。其實(shí)理清上面情況也是有跡可循的,就以定義對(duì)象里的方法里傳入函數(shù)為例:情形一:傳入的參數(shù)是函數(shù)的別名,那么函數(shù)的this就是指向window;情形二:傳入的參數(shù)是被new過的構(gòu)造函數(shù),那么this就是指向?qū)嵗膶?duì)象本身;情形三:如果我們想把被傳入的函數(shù)對(duì)象里this的指針指向外部字面量定義的對(duì)象,那么我們就是用apply和call
每個(gè)函數(shù)都有兩個(gè)非繼承方法:apply()和call(),這兩個(gè)方法的用途都是在特定作用域內(nèi)調(diào)用函數(shù),實(shí)際上等于設(shè)置函數(shù)體內(nèi)this對(duì)象的值。
首先,apply()方法接受兩個(gè)參數(shù):一個(gè)是其中運(yùn)行函數(shù)的作用域,另一個(gè)是參數(shù)數(shù)組。其中參數(shù)可以是Array實(shí)例,也可以是arguments對(duì)象。
call()方法與apply()方法的作用相同,它們的區(qū)別在于接收參數(shù)的方式不同,第一個(gè)參數(shù)是作用域,變化的只是其余參數(shù)都是直接傳遞給函數(shù)的。也就是在使用call()方法時(shí),傳遞給函數(shù)的參數(shù)必須逐個(gè)列舉出來。
使用call()與apply()方法來擴(kuò)充作用域最大好處,對(duì)象不需要與方法有任何耦合關(guān)系,
4、bind()方法支持此方法的瀏覽器有IE9+、Firefox4+、Safari5.1+、Opera12+、Chrome。它是屬于ECMAScript5的方法。直接看例子:
window.color = "red"; var o = { color: "blue" }; function sayColor(){ alert(this.color);}var OSayColor = sayColor.bind(o);OSayColor(); //blue