一、用途javascript
1)apply,call和bind都是 用來改變this的指向java
2)apply和call會讓當前函數當即執行,而bind會返回一個函數,後續須要的時候再調用執行數組
二、this指向問題app
this的指向有如下四種狀況:函數
1)若是函數中的this沒有調用對象,則this指向window(嚴格模式下,this爲undefined)this
2)若是函數中this被不包含子對象的對象調用,則this指向調用它的對象spa
3)若是函數中this被包含多級對象的對象調用,則this指向調用它的上一級對象prototype
4)若是咱們調用了對象,並將其賦值給某個變量,而後在須要的時候再去調用執行它,則此時this也是指向的window對象,如:code
var a = obj.myFunc;對象
a();
var name="zhang"; var age=18; var obj={ name:"liu", myAge:this.age, myFun:function(){ console.log(this); // this指向obj console.log(this.name+";"+this.age) } } obj.myAge // 18 obj.myFun()
上圖是咱們很經常使用的一個對象屬性的獲取和方法的調用,在咱們獲取obj.myAge屬性時,這裏的this實際是window對象,因此咱們去找window.age,找到的是全局參數age=18
在調用myFun()方法時,本着誰調用this就指向誰的基本原則,此時this指向的是obj對象,因此咱們輸出的this.name爲liu,this.age爲undefined
上面的例子若是不太好理解的話,咱們看下面這個更直觀的例子:
var name="zhangsan"; function showName(){ console.log(this); console.log(this.name); } show();
咱們在這裏直接定義了一個方法,而且調用了它,上面說了,誰調用函數,函數裏面的this就指向誰,可是咱們這裏直接調用了show(),並無明確說明是誰調用了它啊,其實這裏咱們能夠理解爲window.show(),即this其實是指向的window。
三、apply和call
1)先來看看call是如何實現的:
Function.prototype.call=function(context){ context=context?Object(context):window; context.fn=this; var args=[]; for(var i=1;i<arguments.length;i++){ args.push("arguments["+i+"]"); } var r = eval("context.fn("+args+")") delete context.fn; return r; }
var name="test"
function demo(){
console.log(this)
console.lot(this.name)
}
demo.call();
1) 當咱們傳遞了context時,context爲咱們傳遞的對象;不然爲window對象。
2) 誰調用,this指向誰,咱們經過demo.call 調用了call方法,因此這裏的this指向的時demo函數
3)將傳遞的參數放進args中
4)經過eval函數執行咱們的context.fn,即上面的demo函數
5)demo函數中,this指向的時call方法中的context,這裏時window對象
6)this.name即window.name
2)call實際上是apply的一個語法糖,他們的做用都是用於改變上下文的指向,區別在於,call接受多個參數,而apply接受的是一個數組
var db={
name:"dema"
}
var obj={ name:"obj", myFunc:function(from,to){ console.log(this); console.log(this.name+"來自:"+from,+"去往:"+to); } }
obj.myFunc.call(null,'北京','上海') // this 指向window,this.name=undefined,from=北京,to=上海
obj.myFunc.call(db,'北京','上海'); // this指向db,this.name='dema',from=北京,to=上海
obj.myFunc.apply(db,['北京','上海']); // this指向db,this.name='dema',from=北京,to=上海
上面例子中,咱們分別調用了call和apply,並傳入了參數null,db和地名,從上面的call的實現中,能夠看到,咱們接受的第一個參數是上下文context,用於改變this的指向。
因此上面第一行,傳入的context爲null,則this指向window,第二行和第三行,都傳人了context爲db,因此this此時是指向db的,即this.name=db.name
四、bind
bind也是用於改變上下文的指向,它和call同樣,接受多個參數。
bind和apply,call的區別在於,bind返回一個方法,用於後面調用,apply和call會直接執行
function print(a,b,c){ console.log(a,b,c) } var fn = print.bind(null,'D') fn('A','B','C') // D,A,B