一直沒怎麼使用過JavaScript中的bind,call和apply, 今天看到一篇比較好的文章,以爲講的比較透徹,因此記錄和總結以下javascript
首先要理解的第一個概念,JavaScript中函數調用的方式,總結下來,有如下4種java
1. 方法調用程序員
2. 正常函數調用數組
3. 構造器函數調用瀏覽器
4. apply/call 調用app
要明白的第2個概念, JavaScript 中的函數,不管是上面哪一種函數調用方式,除了你函數聲明時定義的形參外,還會自動給函數添加兩個形參,分別是this 和 arguments函數
要明白的第3個概念, Javascript中的函數,存在函數上下文(context) 這麼一個概念, 而函數上下文又存在【定義時上下文】,【運行時上下文】,【上下文是能夠改變的】這樣子的狀況, 而第2個概念中的this, 指向的就是當前函數中的上下文this
要明白的第4個概念, 也是咱們今天在這裏要講的call, apply函數的目的 => 它們在JavaScript函數中存在的目的,就是爲了改變某個函數運行時的上下文(context)而存在的, 換句話說,是爲了改變函數體內部this的指向spa
如今咱們一個一個來看prototype
1. 方法調用函數的方式
應該能夠理解,所謂方法調用函數的方式,就是說把一個函數定義爲一個對象的方法,而後經過調用這個對象的該方法,來達到調用該函數的目的
直接上代碼
var myValue = { para: 5, setFunc: function(xvalue){ this.para = xvalue; } } myValue.setFunc(0);
在這裏,函數setFunc做爲變量myValue的也給方法存在,因此使用myValue.setFunc()的形式就能夠調用它。在這裏,函數setFunc中的this,綁定的上下文就是myValue, 因此this.para取到的就是對象myValue的para屬性
2. 正常函數調用
function setValue(xvalue) { this.para = xvalue; } setValue(5);
上面,咱們正常的定義了一個函數setValue,而後正常的調用setValue(5). 在這裏,函數setValue裏面的this綁定的是全局對象. 若是這段JavaScript代碼是運行在瀏覽器中,那麼這裏的this指向的就是瀏覽器的全局對象window. 因此這裏this.para 等價於 window.para. 那有人確定會很奇怪,若是當前瀏覽器的window中不存在para屬性呢,那麼這個時候,在這裏,javascript會自動給全局對象window加上para屬性,同時在這裏賦值爲5
3. 構造器函數調用
JavaScript 中的構造函數,你們知道,首先做爲構造函數的函數名首字母須要大寫,在函數內部必須有this關鍵字。 咱們來看一下構造函數的調用
function SetValue(xvalue) { this.para = xvalue; } var myFunc = new SetValue(5);
在這裏,SetValue函數不是一個普通函數,它是一個構造函數, 調用它是使用new 關鍵字來生成一個新的對象myFunc, 在這裏,this綁定的上下文就再也不是window對象了,而是新的對象myFunc
因此 console.log(myFunc.para) // 輸出5
4. apply/call 來調用函數
咱們能夠看到,上面三種函數調用方式,this指向都不同,可是咱們程序員都沒法自定義或者說更改this的綁定指向。 那麼,若是咱們須要在程序中本身指定this的綁定上下文,有沒用方法呢。這就是apply/call的用處了
JavaScript 中全部函數都有一個公共的prototype => Function, 而Function 這個原型自帶了很多的屬性和方法,其中就有apply, call, bind方法。 咱們首先來看看apply 和 call方法
apply => 當一個對象沒有某個方法時,但這個方法在其餘地方存在。可能使用這個方法的apply方法,把這個方法運用到這個對象上。 它有兩個參數 apply(thisObj, [arg1,arg2,arg3...])
第1個參數是傳遞給這個函數用來綁定this的值(指定這裏this所綁定的上下文是哪個)
第2個參數是一個數組
咱們直接上代碼,來看一個例子
function setValue(xvalue) { this.para = xvalue; } var applyObj = {}; setValue.apply(applyObj,[10]); alert(setValue.para); // undefined alert(applyObj.para); //10
能夠看到,剛開始對象applyObj是咱們定義的一個空對象,而後經過函數原型默認持有的apply方法,咱們把函數setValue經過apply方法應用到空對象applyObj上去,使得對象applyObj擁有了setValue方法,同時,經過第一個參數,指定this所綁定的當前上下文是applyObj對象,傳入的參數爲10
call 方法和apply方法幾乎沒有區別,惟一的區別是, 它的第二個參數不是以數組的形式,而是經過逗號來列出參數的形式 call(thisObj,arg1,arg2,arg3...) 咱們直接來看代碼
function addValue(xvalue, yvalue) { this.para = xvalue + yvalue; } var applyObj = {}; addValue.call(applyObj,2,3); alert(addValue.para); // undefined alert(applyObj.para); //5
固然, 若是在call 或者apply方法中,你傳入的第一個參數是null, 那麼在這種狀況下,函數中的this 指向的依然會是全局對象window
而後,咱們來看一看bind
bind的功能和上面同樣,它接受的參數和call同樣. 惟一的區別是,函數使用bind方法後會生成一個新的函數,你想何時調用新的函數,就何時調用. 咱們來看一個例子
var myObj = { "x" : 4 }; function addValue(y) { alert(this.x + y); } addValue.apply(myObj, [5]); addValue.call(myObj, 5); var foo1 = addValue.bind(myObj, 5); foo1();