apply,call和bind的使用及區別


1、用途

  1)apply,call和bind都是 用來改變this的指向

  2)apply和call會讓當前函數立即執行,而bind會返回一個函數,后續需要的時候再調用執行

2、this指向問題

this的指向有以下四種情況:

  1)如果函數中的this沒有調用對象,則this指向window(嚴格模式下,this為undefined)

  2)如果函數中this被不包含子對象的對象調用,則this指向調用它的對象

  3)如果函數中this被包含多級對象的對象調用,則this指向調用它的上一級對象

  4)如果我們調用了對象,並將其賦值給某個變量,然后在需要的時候再去調用執行它,則此時this也是指向的window對象,如:

    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);
}
showName();

我們在這里直接定義了一個方法,並且調用了它,上面說了,誰調用函數,函數里面的this就指向誰,但是我們這里直接調用了showName(),並沒有明確說明是誰調用了它啊,其實這里我們可以理解為window.showName()即this實際上是指向的window。

 

3、apply和call

  1)先來看看call是如何實現的:

Function.prototype.call=function(context){
// 這里的this指向demo函數
console.log(this); context=context?Object(context):window; context.fn=this; var args=[];
// 參數從1開始循環因為第一個參數是context for(var i=1;i<arguments.length;i++){ args.push("arguments["+i+"]"); }
// 這里執行context.fn() 即上面的demo(),所以this指向了context,但是因為我們沒有傳遞context,所以this指向了window 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

4、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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM