JS中的call、apply、bind方法

在JavaScript中,callapplybindFunction對象自帶的三個方法,這三個方法的主要做用是改變函數中的this指向。javascript

callapplybind方法的共同點和區別:
applycallbind 三者都是用來改變函數的this對象的指向的;
applycallbind 三者第一個參數都是this要指向的對象,也就是想指定的上下文(函數的每次調用都會擁有一個特殊值——本次調用的上下文(context)——這就是this關鍵字的值。);
applycallbind 三者均可以利用後續參數傳參;
bind 是返回對應函數,便於稍後調用;applycall 則是當即調用 。java

1、call數組

call()
語法:app

call([thisObj[,arg1[, arg2[, [,.argN]]]]])複製代碼

定義:調用一個對象的一個方法,以另外一個對象替換當前對象。函數

說明: call 方法能夠用來代替另外一個對象調用一個方法。
call 方法可將一個函數的對象上下文從初始的上下文改變爲由 thisObj 指定的新對象。ui

thisObj的取值有如下4種狀況:
(1) 不傳,或者傳null,undefined, 函數中的this指向window對象
(2) 傳遞另外一個函數的函數名,函數中的this指向這個函數的引用
(3) 傳遞字符串、數值或布爾類型等基礎類型,函數中的this指向其對應的包裝對象,如 String、Number、Boolean
(4) 傳遞一個對象,函數中的this指向這個對象this

function a(){   
  console.log(this);   //輸出函數a中的this對象
}       

function b(){}       

var c={name:"call"};    //定義對象c 

a.call();   //window
a.call(null);   //window
a.call(undefined);   //window
a.call(1);   //Number
a.call('');   //String
a.call(true);   //Boolean
a.call(b);   //function b(){}
a.call(c);   //Object複製代碼

若是你不理解上面的,不要緊,咱們再來看一個例子:spa

function class1(){   
  this.name=function(){   
    console.log("我是class1內的方法");   
  }   
}   
function class2(){ 
  class1.call(this);  //此行代碼執行後,當前的this指向了class1(也能夠說class2繼承了class1) 
}   

var f=new class2();   
f.name();   //調用的是class1內的方法,將class1的name方法交給class2使用複製代碼

經常使用例子:
(1)code

function eat(x,y){   
  console.log(x+y);   
}   
function drink(x,y){   
  console.log(x-y);   
}   
eat.call(drink,3,2);

輸出:5複製代碼

這個例子中的意思就是用 eat 來替換 drink,eat.call(drink,3,2) == eat(3,2) ,因此運行結果爲:console.log(5);
注意:js 中的函數實際上是對象,函數名是對 Function 對象的引用。對象

(2)

function Animal(){   
  this.name="animal";   
  this.showName=function(){   
    console.log(this.name);   
  }   
}   
function Dog(){   
  this.name="dog";   
}   
var animal=new Animal();   
var dog=new Dog();       

animal.showName.call(dog);

輸出:dog複製代碼

在上面的代碼中,咱們能夠看到Dog裏並無showName方法,那爲何(this.name)的值是dog呢?

關鍵就在於最後一段代碼(animal.showName.call(dog)),意思是把animal的方法放到dog上執行,也能夠說,把animal 的showName()方法放到 dog上來執行,因此this.name 應該是 dog。

(3)繼承

function Animal(name){   
  this.name=name;   
  this.showName=function(){   
    console.log(this.name);   
  }   
}   
function Dog(name){   
  Animal.call(this,name);   
}   
var dog=new Dog("Crazy dog");   
dog.showName();

輸出:Crazy dog複製代碼

Animal.call(this) 的意思就是使用 Animal對象代替this對象,那麼Dog就能直接調用Animal的全部屬性和方法。

2、apply()

語法:apply([thisObj[,argArray]])

定義:應用某一對象的一個方法,用另外一個對象替換當前對象。

說明:
若是 argArray 不是一個有效的數組或者不是 arguments 對象,那麼將致使一個 TypeError。
若是沒有提供 argArray 和 thisObj 任何一個參數,那麼 Global 對象將被用做 thisObj, 而且沒法被傳遞任何參數。

call 和 apply的區別
對於 apply、call 兩者而言,做用徹底同樣,只是接受參數的方式不太同樣。

function class1(args1,args2){       
  this.name=function(){      
   console.log(args,args);      
  }     
}     
function class2(){    
  var args1="1";
  var args2="2";
  class1.call(this,args1,args2);  
  /*或*/
  class1.apply(this,[args1,args2]);
}

var c=new class2();   
c.name();

輸出:1 2複製代碼

call 須要把參數按順序傳遞進去,而 apply 則是把參數放在數組裏。

既然二者功能同樣,那該用哪一個呢?

在JavaScript 中,某個函數的參數數量是不固定的,所以要說適用條件的話,當你的參數是明確知道數量時用 call ;而不肯定的時候用 apply,而後把參數 push 進數組傳遞進去。當參數數量不肯定時,函數內部也能夠經過 arguments 這個類數組對象來遍歷全部的參數。

3、bind
bind是在EcmaScript5中擴展的方法(IE6,7,8不支持)
bind() 方法與 apply 和 call 很類似,也是能夠改變函數體內 this 的指向。

  MDN的解釋是:bind()方法會建立一個新函數,稱爲綁定函數,當調用這個綁定函數時,綁定函數會以建立它時傳入 bind()方法的第一個參數做爲 this,傳入 bind() 方法的第二個以及之後的參數加上綁定函數運行時自己的參數按照順序做爲原函數的參數來調用原函數。

注意:bind方法的返回值是函數

var bar=function(){   
  console.log(this.x);   
}
var foo={ 
     x:3   
}   
bar();  
bar.bind(foo)();
 /*或*/
var func=bar.bind(foo);   
func();

輸出:
undefined
3複製代碼
相關文章
相關標籤/搜索