apply()和call()的真正用武之地是能夠擴充函數來一運行的作用域,如果我們相用傳統方法實現
1、每個函數都包含兩個非繼承而來的方法:apply()和call()。2、他們的用途相同,都是在特定的作用域中調用函數。3、接收參數方面不同,apply()接收兩個參數,一個是函數運行的作用域(this),另一個是參數數組。call()方法第一個參數與apply()方法相同,但傳遞給函數的參數必須列舉出來。
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);
運行結果為: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中,我們發現apply()和call()的真正用武之地是能夠擴充函數賴以運行的作用域,如果我們想用傳統的方法實現,請見下面的代碼:
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!
見加紅的代碼,我們發現,要想讓HelloName()函數的作用域在對象myObject上,我們需要動態創建myObject的HelloName屬性,此屬性作為指針指向HelloName()函數,這樣,當我們調用myObject.HelloName()時,
函數內部的this變量就指向myObjecct,也就可以調用該對象的內部其他公共屬性了。通過分析例2,我們可以看到call()和apply()函數的真正運用之處,在實際項目中,還需要根據實際靈活加以處理!一個小問題:再看一看函數中定義函數時,this變量的情況
function temp1() { console.log(this); //Object {} function temp2() { console.log(this); //Window} temp2();}var Obj = {};temp1.call(Obj); //運行結果見上面綠色的注釋
執行結果與下面的相同:
function temp1() { console.log(this); temp2();} function temp2() { console.log(this);}var Obj = {};temp1.call(Obj);
call方法:調用一個對象的一個方法,以另一個對象替代當前對象
call([thisObj[,arg1[, arg2[, [,.argN]]]]]) 參數:thisObj 可選項:將被用作當前對象的對象 arg1 arg2 argN
call方法可以用來代替另一個方法調用一個方法。call方法可以將一個函數的對象從初始的上下文改變為由thisObj制定的新對象
如果沒有提供thisObj參數,那么Global對象將被用作thisObj
obj1.method1.call(obj2,argument1,argument2);
call 的作用就是把obj1的方法放到obj2上使用,然后把arguments1這些作為參數傳入(把作用于obj1上的方法轉移作用到obj2)
表面原因就是我們定義對象使用對象的字面表示法,字面表示法在簡單的表示里我們很容易知道this指向對象本身,但是這個對象會有方法,方法的參數可能會是函數,
而這個函數的定義里也可能會使用this指針,如果傳入的函數沒有被實例化過和被實例化過,this的指向是不同,
有時我們還想在傳入函數里通過this指向外部函數或者指向被定義對象本身,這些亂七八糟的情況使用交織在一起導致this變得很復雜,結果就變得糊里糊涂。其實理清上面情況也是有跡可循的,就以定義對象里的方法里傳入函數為例:情形一:傳入的參數是函數的別名,那么函數的this就是指向window;情形二:傳入的參數是被new過的構造函數,那么this就是指向實例化的對象本身;情形三:如果我們想把被傳入的函數對象里this的指針指向外部字面量定義的對象,那么我們就是用apply和call
每個函數都有兩個非繼承方法:apply()和call(),這兩個方法的用途都是在特定作用域內調用函數,實際上等于設置函數體內this對象的值。
首先,apply()方法接受兩個參數:一個是其中運行函數的作用域,另一個是參數數組。其中參數可以是Array實例,也可以是arguments對象。
call()方法與apply()方法的作用相同,它們的區別在于接收參數的方式不同,第一個參數是作用域,變化的只是其余參數都是直接傳遞給函數的。也就是在使用call()方法時,傳遞給函數的參數必須逐個列舉出來。
使用call()與apply()方法來擴充作用域最大好處,對象不需要與方法有任何耦合關系,
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