學習前端的菜雞對JS的call,apply,bind的通俗易懂理解

   call,apply,bind

 

在JavaScript中,callapplybindFunction對象自帶的三個方法,都是爲了改變函數體內部 this 的指向。javascript

           apply 、 call 、bind 三者第一個參數都是 this 要指向的對象,也就是想指定的上下文;html

           apply 、 call 、bind 三者均可以利用後續參數傳參;java

                        bind 是返回對應 函數,便於稍後調用;apply 、call 則是當即調用 。數組

 

——————————————————————————————————————————————————————————————————————————-app

例子:dom

1.函數

   function fruits() {}
 
       fruits.prototype = {
             color: 'red',
             say: function() {
             console.log('My color is' + this.color);  
                 }
            }
 
     var apple = new fruits;
    apple.say();   // 此時方法裏面的this 指的是fruits
    // 結果: My color is red  
 

可是若是咱們有一個對象 banana= {color : 'yellow'} ,咱們不想從新定義 say 方法,那麼咱們能夠經過 call 或 apply 用 apple 的 say 方法:ui

banana = {
color: 'yellow'
}
apple.say.call(banana); //此時的this的指向已經同過call()方法改變了,指向的是banana,this.color就是banana.color='yellow';
//結果是My color is yellow  
apple.say.apply(banana);//同理,此時的this的指向已經同過apply()方法改變了,指向的是banana,this.color就是banana.color ='yellow';
//My color is yellow
// 若是傳入的是 null:

apple.say.apply(null); // null是window下的,此時,this 就指向了window ,可是window下並無clolr這個屬性,所以this.clolr就是window.color=undefined;
//My color is undefined

 

2.對於 apply、call 兩者而言,做用徹底同樣,只是接受 參數 的方式不太同樣。call 是把參數按順序傳遞進去,而 apply 則是把參數放在數組 裏。this

var array1 = [12,'foo',{name:'Joe'},-2458];
var array2 = ['Doe' , 555 , 100];
Array.prototype.push.call(array1, array2);
// 這裏用 call 第二個參數不會把 array2 當成一個數組,而是一個元素
//等價於array1.push(‘‘'Doe' , 555 , 100’’);
//array1.length=5;
 
Array.prototype.push.apply(array1, array2); // 這裏用 apply 第二個參數是一個數組
 
// 等價於:  array1.push('Doe' , 555 , 100);
//array1.length=7;

3.類(僞)數組使用數組方法

var divElements = document.getElementsByTagName('div'); //雖然 divElements 有length屬性,可是他是一個僞數組,不能使用數組裏面的方法
Array.isArray(divElements);// false
 
var domNodes = Array.prototype.slice.call(document.getElementsByTagName('div'));
// 將數組對象Array裏的this指向僞數組document.getElementsByTagName('div'), 
//
slice() 方法可從已有的數組中返回選定的元素,不傳參數是,返回整個數組
Array.isArray(domNodes);// true

4. 驗證一個對象的類型能夠用:

Object.prototype.toString.call(obj) 

 

5.bind() 方法,MDN 的解釋是:bind() 方法會建立一個 新函數,稱爲綁定函數,當調用這個綁定函數時,spa

綁定函數會以建立它時傳入 bind() 方法的第一個參數 做爲 this,傳入 bind() 方法的 第二個以及之後的參

數加上綁定函數運行時自己的參數按照順序做爲原函數的參數來調用原函數。

var bar = function(){
    console.log(this.x);
}
var foo = {
    x:3
}
bar(); // undefined
var func = bar.bind(foo); //此時this已經指向了foo,可是用bind()方法並不會當即執行,而是建立一個新函數,若是要直接調用的話 能夠 bar.bind(foo)()


func(); // 3

6.在 Javascript 中,屢次 bind() 是無效的。更深層次的緣由, bind() 的實現,至關於使用函數在內部包了一個 call / apply ,第二次 bind() 至關於再包住第一次 bind() ,故第二次之後的 bind 是沒法生效的。

var bar = function(){
  console.log(this.x);
}
var foo = {
  x:3
}
var sed = {
  x:4
}
var func = bar.bind(foo).bind(sed);
func(); //3
  
var fiv = {
  x:5
}
var func = bar.bind(foo).bind(sed).bind(fiv);
func(); //3

 

7.apply、call、bind 三者相比較,之間又有什麼異同呢?什麼時候使用 apply、call,什麼時候使用 bind 呢。簡單的一個例子:

var obj = {
  x: 81,
};
  
var foo = {
  getX: function() {
    return this.x;
  }
}
console.log(foo.getX.bind(obj)());  //81
console.log(foo.getX.call(obj));    //81
console.log(foo.getX.apply(obj));   //81

 

參考:
相關文章
相關標籤/搜索