call、apply、bind 的用法和區別

call、apply、bind 的用法和區別

首先:call、apply、bind的作用是改變函數運行時的this的指向

var zr = {
        a: 1,
        fn: function () {
            console.log(this.a); //1
        }
    }
    zr.fn();
    //相當於zr.fn.call(zr)或者zr.fn.apply(zr);
var zr = {
        a: 1,
        b: {
            a: 2,
            fn: function () {
                console.log(this.a);
            }
        }
    }
    //this指向zr對象中的b,所以打印的是this上一級對象,所以輸出2
    zr.b.fn(); //2
    //此處使用call或者apply函數 把this從指向b改變爲指向zr  
    console.log(zr.b.fn.call(zr)) //1
    console.log(zr.b.fn.apply(zr)) //1
    //也就相當於是變成了
    var zr = {
        a: 1,
        fn: function () {
            console.log(this.a); //1
        }
    }
//由於普通函數(沒有父級對象)沒有任何調用,所以其this就指向window;
function zr() {
        var username = "睿睿";
        console.log(this.username); //undefined
        console.log(this); //Window
    }
    zr();
    //相當於zr.call(undefined)

所以setTimeout作爲一個普通的回調函數,其this是指向window;這就是setTimeout()丟失this的原因;所以在使用setTimeout()的時候:var _this=this;

接下來進入正題

call()可以傳n個參數,但是第一個參數是this將要指向的對象 當第一個參數爲null或者undefined的時候,this默認指向window;之後的參數相當於普通傳參一樣自定義使用;

apply()只可以傳倆個參數,第一個參數和call()的第一個參數一樣,是this將要指向的對象;當第一個參數爲null或者undefined的時候,this默認指向window;;第二個參數是一個數組,相當於把call()除第一個參數外的所有參數放到一個數組中;

var zr = {
        a: 1,
        b: {
            a: 2,
            c: {
                a: 3,
                fn: function (x , y) {
                    console.log(this.a);
                    console.log(x+y);
                }
            }

        }
    }
    //此處使用call或者apply函數 把this從指向c改變爲指向b 
    zr.b.c.fn.call(zr.b ,1 , 2) //2     3
    zr.b.c.fn.apply(zr.b ,[1 , 2] ) //2     3
     //此處使用call或者apply函數 把this從指向c改變爲指向zr
    zr.b.c.fn.call(zr ,1 , 2) //1     3
    zr.b.c.fn.apply(zr ,[1 , 2] ) //1     3
     //此處使用call或者apply函數 第一個參數傳null,this默認指向window
    zr.b.c.fn.call(null ,1 , 2) //undefined  3
    zr.b.c.fn.apply(null ,[1 , 2] ) //undefined    3

其實apply() 和 call() 的用法基本上相同, 唯一的差別就是:當函數需要傳遞>1個變量時, apply() 可以接受一個數組作爲參數, call() 必須接受>1個的單獨變量。

bind()的傳參方式和call()很相似,第一個參數是this將要指向的對象,第一個傳null得話不改變this指向,並且可以在後續的調用中去傳入參數

//後續的調用中去傳入參數
function zr(a, b, c) {
        return a * b * c;
    }

    var fn = zr.bind(null, 2);

    //相當於
    //function fn(2, b, c) {
        //return 2 * b * c;
    //}
    
    console.log(fn(3, 4));//24
    
    //相當於
    //function fn(2, 3, 4) {
        //return 2 * 3 * 4;
    //}


    //bind()返回的一個改變了 this 之後的新函數;原函數zr中的this並沒有改變;
    var obj = {
        username:'睿睿'
    }
    function zr () {
        console.log(this.username)
    }
    var bindfn =zr.bind(obj)
    bindfn()//睿睿
    //zr () {
        //console.log(this.username)
    //}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章