- call、apply:
在 javascript 中,call 和 apply 都是爲了改變某個函數運行時的上下文(context)而存在的,換句話說,就是爲了改變函數體內部 this 的指向。javascript
JavaScript 的一大特色是,函數存在「定義時上下文」和「運行時上下文」以及「上下文是能夠改變的」這樣的概念。java
call能夠傳遞一個thisArgs參數和一個參數列表,thisArgs 指定了函數在運行期的調用者,也就是函數中的 this 對象,而參數列表會被傳入調用函數中。thisArgs 的取值有如下4種狀況:
(1) 不傳,或者傳null,undefined, 函數中的 this 指向 window 對象
(2) 傳遞另外一個函數的函數名,函數中的 this 指向這個函數的引用
(3) 傳遞字符串、數值或布爾類型等基礎類型,函數中的 this 指向其對應的包裝對象,如 String、Number、Boolean
(4) 傳遞一個對象,函數中的 this 指向這個對象數組
function a() { console.log(this); //輸出函數a中的this對象 } function b() {} //定義函數b var obj = { name: 'hehe' }; //定義對象obj 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(obj); //Object
這是call 的核心功能,它容許你在一個對象上調用該對象沒有定義的方法,而且這個方法能夠訪問該對象中的屬性。app
function animals() {} animals.prototype = { type: "dog", say: function() { console.log("I am a " + this.type); } } var dog = new animals(); dog.say(); //I am a dog var cat = {type:'cat'}; dog.say.call(cat); //I am a cat
所以,能夠看出 call 和 apply 是爲了動態改變 this 而出現的,當一個 object 沒有某個方法(本栗子中cat沒有say方法),可是其餘的有(本栗子中dog有say方法),咱們能夠藉助call或apply用其它對象的方法來操做。函數
apply、call 的區別:this
對於 apply、call 兩者而言,做用徹底同樣,只是接受參數的方式不太同樣。prototype
對象.函數名.call(thisArgs, arg1, arg2); 對象.函數名.apply(thisArgs, [arg1, arg2])
其中 this 是你想指定的上下文,他能夠是任何一個 JavaScript 對象(JavaScript 中一切皆對象),call 須要把參數按順序傳遞進去,而 apply 則是把參數放在數組裏。code
- bind:
bind是ES5 新增的一個方法,它的傳參和call相似,但又和 call/apply 有着顯著的不一樣,即調用 call 或 apply 都會自動執行對應的函數,而 bind 不會執行對應的函數,只是返回了對函數的引用。對象
MDN的解釋是:bind()方法會建立一個新函數,稱爲綁定函數,當調用這個綁定函數時,綁定函數會以建立它時傳入 bind()方法的第一個參數做爲 this,傳入 bind() 方法的第二個以及之後的參數加上綁定函數運行時自己的參數按照順序做爲原函數的參數來調用原函數。事件
var obj = { id : 1, eventBind: function(){ var _this = this; $('.btn').on('click',function(event) { alert(this.id); //undefined alert(_this.id); //1 }); } } obj.eventBind();//沒有這句話,click事件不執行
因爲 Javascript 特有的機制,上下文環境在 eventBind:function(){ } 過渡到 $('.btn').on('click',function(event) { }) 發生了改變,上述使用變量保存 this 這些方式都是有用的,也沒有什麼問題。固然使用 bind() 能夠更加優雅的解決這個問題:
var obj = { id : 1, eventBind: function(){ $('.btn').on('click',function(event) { alert(this.id); //1 }.bind(this)); } } obj.eventBind();//沒有這句話,click事件不執行
- call、apply和bind的區別:
var obj = { x: 88, }; var foo = { getX: function() { return this.x; } } console.log(foo.getX.bind(obj)()); //88 console.log(foo.getX.call(obj)); //88 console.log(foo.getX.apply(obj)); //88
三個輸出的都是88,可是注意使用 bind() 方法後面多了對括號。
也就是說,區別就是,當你但願改變上下文環境以後並不是當即執行,而是回調執行的時候,使用 bind() 方法;而 apply/call 則會當即執行函數。