call和apply的使用和區別再也不作闡述,能夠參考個人另外一篇隨筆《JavaScript中call和apply方法的使用》(https://www.cnblogs.com/lcr-smg/p/10067398.html),這裏只是針對bind的用法及與call和apply二者的區別。html
bind的用法app
bind() 方法與 apply 和 call 很類似,也是能夠改變函數體內 this 的指向。函數
MDN的解釋是:bind()方法會建立一個新函數,稱爲綁定函數,當調用這個綁定函數時,綁定函數會以建立它時傳入 bind()方法的第一個參數做爲 this,傳入 bind() 方法的第二個以及之後的參數加上綁定函數運行時自己的參數按照順序做爲原函數的參數來調用原函數。直接來看看具體如何使用,在常見的單體模式中,一般咱們會使用 _this , that , self 等保存 this ,這樣咱們能夠在改變了上下文以後繼續引用到它。 像這樣:this
1 var foo = { 2 bar : 1, 3 eventBind: function(){ 4 var _this = this; 5 $('.someClass').on('click',function(event) { 6 /* Act on the event */ 7 console.log(_this.bar); //1 8 }); 9 } 10 }
因爲 Javascript 特有的機制,上下文環境在 eventBind:function(){ } 過渡到 $('.someClass').on('click',function(event) { }) 發生了改變,上述使用變量保存 this 這些方式都是有用的,也沒有什麼問題。固然使用 bind() 能夠更加優雅的解決這個問題:spa
1 var foo = { 2 bar : 1, 3 eventBind: function(){ 4 $('.someClass').on('click',function(event) { 5 /* Act on the event */ 6 console.log(this.bar); //1 7 }.bind(this)); 8 } 9 }
在上述代碼裏,bind() 建立了一個函數,當這個click事件綁定在被調用的時候,它的 this 關鍵詞會被設置成被傳入的值(這裏指調用bind()時傳入的參數)。所以,這裏咱們傳入想要的上下文 this(其實就是 foo ),到 bind() 函數中。而後,當回調函數被執行的時候, this 便指向 foo 對象。再來一個簡單的栗子:code
1 var bar = function(){ 2 console.log(this.x); 3 } 4 var foo = { 5 x:3 6 } 7 bar(); // undefined 8 var func = bar.bind(foo); 9 func(); // 3
這裏咱們建立了一個新的函數 func,當使用 bind() 建立一個綁定函數以後,它被執行的時候,它的 this 會被設置成 foo , 而不是像咱們調用 bar() 時的全局做用域。有個有趣的問題,若是連續 bind() 兩次,亦或者是連續 bind() 三次那麼輸出的值是什麼呢?像這樣:htm
1 var bar = function(){ 2 console.log(this.x); 3 } 4 var foo = { 5 x:3 6 } 7 var sed = { 8 x:4 9 } 10 var func = bar.bind(foo).bind(sed); 11 func(); //? 12 13 var fiv = { 14 x:5 15 } 16 var func = bar.bind(foo).bind(sed).bind(fiv); 17 func(); //?
答案是,兩次都仍將輸出 3 ,而非期待中的 4 和 5 。緣由是,在Javascript中,屢次 bind() 是無效的。更深層次的緣由, bind() 的實現,至關於使用函數在內部包了一個 call / apply ,第二次 bind() 至關於再包住第一次 bind() ,故第二次之後的 bind 是沒法生效的。對象
那麼 apply、call、bind 三者相比較,之間又有什麼異同呢?什麼時候使用 apply、call,什麼時候使用 bind 呢。簡單的一個栗子:blog
1 var obj = { 2 x: 81, 3 }; 4 5 var foo = { 6 getX: function() { 7 return this.x; 8 } 9 } 10 11 console.log(foo.getX.bind(obj)()); //81 12 console.log(foo.getX.call(obj)); //81 13 console.log(foo.getX.apply(obj)); //81
三個輸出的都是81,可是注意看使用 bind() 方法的,他後面多了對括號。事件
也就是說,區別是,當你但願改變上下文環境以後並不是當即執行,而是回調執行的時候,使用 bind() 方法。而 apply/call 則會當即執行函數。
總結: