一說到js中的call、apply、bind方法,就必定會和this聯繫起來,百分之九十以上的問題都是有關這三個函數方法中this的指向問題,在前端面試題中很是的常見,掌握了這三個方法的this指向問題,不只能夠在面試官前侃侃而談,加深面試官對你的印象,並且能夠提升咱們js代碼的編碼水平和編碼水平,做爲一個前端這是咱們必須掌握的基本知識。 再說他們三個以前,咱們先來講下this吧,懂了this的指向問題,也就掌握了這三個方法的精髓。html
this是函數內部的一個特殊的對象,,this引用的是函數據以執行的環境對象——或者也能夠說是this值(當在網頁的全局做用域調用函數時,this 對象引用的就是 window )。簡單的說this指向調用該函數的環境對象。再簡單一點就是誰調用它就指向誰,下面具體的說說this的調用指向前端
var x = 1;
function test() {
console.log(this.x);
}
test(); // 1 this指向全局對象
複製代碼
var obj = {
n:'1',
m:function test() {
console.log(this.n);
}
};
obj.m()//1 this指向obj
複製代碼
var x = 2;
function Test() {
 this.x = 1;
}
var obj = new Test();
obj.x // 1 this 指向obj
x=2 //說明this並非指向的是window
複製代碼
備註:下面的兩個this指向參考了這個做者的文章,在通讀以後以爲寫的很透徹明瞭,就直接節選了部分,本身也就不在羅嗦了。面試
連接:zhuanlan.zhihu.com/p/42145138數組
事件綁定共有三種方式:行內綁定、動態綁定、事件監聽;行內綁定的兩種狀況:瀏覽器
<input type="button" value="按鈕" onclick="clickFun()">
<script>
function clickFun(){
this // 此函數的運行環境在全局window對象下,所以this指向window;
}
</script>
<input type="button" value="按鈕" onclick="this">
<!-- 運行環境在節點對象中,所以this指向本節點對象 -->
複製代碼
行內綁定事件的語法是在html節點內,以節點屬性的方式綁定,屬性名是事件名稱前面加'on',屬性的值則是一段可執行的 JS 代碼段;而屬性值最多見的就是一個函數調用;當事件觸發時,屬性值就會做爲JS代碼被執行,當前運行環境下沒有clickFun函數,所以瀏覽器就須要跳出當前運行環境,在整個環境中尋找一個叫clickFun的函數並執行這個函數,因此函數內部的this就指向了全局對象window;若是不是一個函數調用,直接在當前節點對象環境下使用this,那麼顯然this就會指向當前節點對象;動態綁定與事件監聽:bash
<input type="button" value="按鈕" id="btn">
<script>
var btn = document.getElementById('btn');
btn.onclick = function(){
this ; // this指向本節點對象
}
</script>
複製代碼
由於動態綁定的事件本就是爲節點對象的屬性(事件名稱前面加'on')從新賦值爲一個匿名函數,所以函數在執行時就是在節點對象的環境下,this天然就指向了本節點對象;app
var obj = {
fun:function(){
this ;
}
}
setInterval(obj.fun,1000); // this指向window對象
setInterval('obj.fun()',1000); // this指向obj對象
複製代碼
setInterval()
是window對象下內置的一個方法,接受兩個參數,第一個參數容許是一個函數或者是一段可執行的 JS 代碼,第二個參數則是執行前面函數或者代碼的時間間隔;函數
在上面的代碼中,setInterval(obj.fun,1000)
的第一個參數是obj對象的fun ,由於 JS 中函數能夠被當作值來作引用傳遞,實際就是將這個函數的地址當作參數傳遞給了 setInterval
方法,換句話說就是setInterval
的第一參數接受了一個函數,那麼此時1000毫秒後,函數的運行就已是在window對象下了,也就是函數的調用者已經變成了window對象,因此其中的this則指向的全局window對象;ui
而在 setInterval('obj.fun()',1000)
中的第一個參數,實際則是傳入的一段可執行的 JS 代碼;1000毫秒後當 JS 引擎來執行這段代碼時,則是經過 obj 對象來找到 fun 函數並調用執行,那麼函數的運行環境依然在 對象 obj 內,因此函數內部的this也就指向了 obj 對象;this
apply方法和call方法都是函數非繼承而來的方法,這兩個方法的用途都是在特定的做用域中調用函數,實際上等於設置函數體內的this對象的值。apply() 方法接收兩個參數:一個是在其中運行函數的做用域,另外一個是參數數組。其中,第二個參數能夠是 Array 的實例,也能夠是arguments對象。
call()方法與apply()方法的做用相同,區別是第二個傳遞給函數的參數必須是一一列舉出來。(對於this的指向問題,只要記住一點,this值指向該方法的第一個參數就能夠了,語法就這樣規定)
var x = 0;
function test() {
 console.log(this.x);
}
var obj = {};
obj.x = 1;
test.apply(obj,[0])//this指向obj
複製代碼
var x = 0;
function test() {
 console.log(this.x);
}
var obj = {};
obj.x = 1;
test.call(obj,0,1,2)//this指向obj
複製代碼
這個方法會建立一個函數的實例,其 this 值會被綁定到傳給 bind() 函數的值。也就是他會返回一個函數。
window.color = "red";
var o = { color: "blue" };
function test(){
alert(this.color);
}
var obj = test.bind(o);//this指向o
obj(); //blue
複製代碼
apply、call的做用同樣,只是第二個參數傳遞方式不一樣,apply要求是數組形式,call要求是將參數一一列舉出來, apply和call都是改變this的指向後就執行函數,而bind是改變this指向後返回一個函數,您得手動再執行這個函數
本文參考阮一峯的this指向文章,以及通讀了數篇關於this指向的問題,造成本身的理解,對於有關摘錄部分也作了原文連接說明,若有紕漏,歡迎指正。