Call,Apply與Bind的兄弟密談

三兄弟來源

call,apply,bind 爲何要叫作三兄弟,是由於他們有一個共同的父親——Function.prototype,因此他們都是實例方法,不妨我們現場"滴血認親"一下javascript

Function.prototype.hasOwnProperty('call'); 
Function.prototype.hasOwnProperty('apply');
Function.prototype.hasOwnProperty('bind');
複製代碼

上面三條語句的返回結果都爲true,算了有圖有真相,上圖java

FUddkF.png

所以,這三兄弟能夠在對象,數組,函數中均可以使用。數組

大哥——Call

call方法,能夠指定所用目標函數的this指向,即函數執行時所在的做用域(上下文),而且在指定的做用域調用這個函數,當即執行。app

var content = {
    number: 2
};

var number = 1;

function func(){
    console.log(this.number);
}
a();  //結果爲1
a.call(); //沒有傳遞參數仍是默認所在的做用域
a.call(content); //指向content的內部做用域,此時結果爲2

複製代碼

即,當咱們執行a函數時,它指向的是全局對象,因此this指向的也就是全局對象;但當咱們幫它指向content對象時,這個函數的執行做用域也就變爲了content對象的做用域函數

Call 傳參

call方法能夠傳遞多個參數,第一個參數即爲指定的this的指向,即要提供這個函數要執行所存在的做用域的傢伙,後面的參數是函數調用時須要使用的參數,直接用","號分割便可。ui

若是 call的第一個參數爲null或者undefined或者this,它等同於指向全局對象。this

二哥——Apply

apply方法身爲二哥,天然是和大哥的做用很是類似,他們都是改變this指向來在制定的做用域中調用這個函數,當即執行,惟一的不一樣可能就是二哥Apply相比較於大哥Call來講它更"挑食"。它只能接收兩個參數,第一個參數爲this指向的對象,第二個參數爲執行時須要的參數,注意,它只要數組做爲他的第二個參數。spa

咱們讓大哥和二哥實現相同的功能來看一下他們的不一樣prototype

function sum(a,b){
    return a + b;
}
sum.call(this,1,2); //結果爲3
sum.apply(this,[1,2]); //結果爲3
複製代碼

因此,當咱們要讓某個數組來執行某種方法時,使用apply方法相較於call方法能方便不少。好比咱們想快速的查找一個數組中的最大值code

var a = [1,2,3,4,5,7,8,9,45,123,111];
Math.max.apply(this,a); // 123
複製代碼

三弟——bind

bind方法用於指定函數內部的this指向,而後返回一個新函數,但它不會當即執行,它只是給這個函數增長了修飾,並無調用它。

var content = {
    number: 2
};

function func(){
    console.log(this.number);
}

//call方法
func.call(content); // 2
//apply方法
func.apply(content); //2
//bind方法
func.bind(content)(); //2
複製代碼

bind的參數要求和大哥同樣,即爲一個一個的傳參.

call 和 apply 方法在調用後會當即執行,而bind則是把做用域修改後的函數返回,須要本身再次手動調用。

三兄弟異同

從上面的例子咱們能夠看到三兄弟十分類似,但也各有千秋。

同:

  • 都用來改變函數的this指向,即做用域。
  • 第一個參數都是用來指定函數內部的this。
  • 均可以在函數調用的時候傳遞原函數所須要的參數。

異:

  • call 和 apply 調用後當即執行,而bind則是把新函數返回,須要再次調用。
  • call 和 bind 傳遞參數是直接傳入,也就是一個一個的傳,而apply 則須要一個數組來做爲第二個參數。
相關文章
相關標籤/搜索