天天看點

javascript基礎之bind、call、apply方法的差別以及如何手動實作

改變this的指向可以用bind,call,apply方法,那這三個方法有什麼差別呢?又如何手動實作這三個方法呢?且往下看:

1、bind、call、apply的差別是什麼?

bind被稱為是綁定函數,其函數内部的this指向建立它時傳入bind的第一個參數,而傳入bind的第二個以及後面的參數則作為原來函數的參數調用原函數,另外bind不會立即執行,而是傳回了一個新的函數。

call和apply都是為了改變函數内部的運作上下文,apply和call的調用傳回函數執行結果。調用call或apply方法,那麼this指向他們的第一個參數,apply的第二個參數是一個參數數組,call的第二個及其以後的參數都是數組裡面的元素,就是說要全部列舉出來;

2、bind、call、apply的怎麼用?

bind文法:

func.bind(thisArg[, arg1[, arg2[, ...]]])
thisArg 當綁定函數被調用時,該參數會作為原函數運作時的this指向。當使用new 操作符調用綁定函數時,該參數無效。
arg1, arg2, ... 當綁定函數被調用時,這些參數将置于實參之前傳遞給被綁定的方法。
           
call文法:

fun.call(thisArg, arg1, arg2, ...)
thisArg::在fun函數運作時指定的this值。需要注意的是,指定的this值并不一定是該函數執行時真正的this值,如果這個函數處于非嚴格模式下,則指定為null和undefined的this值會自動指向全局對象(浏覽器中就是window對象),同時值為原始值(數字,字元串,布爾值)的this會指向該原始值的自動包裝對象。
arg1, arg2, ... 指定的參數清單。
           
apply文法:

fun.apply(thisArg, [argsArray])
thisArg: 在 fun 函數運作時指定的 this 值。需要注意的是,指定的 this 值并不一定是該函數執行時真正的 this 值,如果這個函數處于非嚴格模式下,則指定為 null 或 undefined 時會自動指向全局對象(浏覽器中就是window對象),同時值為原始值(數字,字元串,布爾值)的 this 會指向該原始值的自動包裝對象。
argsArray: 一個數組或者類數組對象,其中的數組元素将作為單獨的參數傳給 fun 函數。如果該參數的值為null 或 undefined,則表示不需要傳入任何參數。從ECMAScript 5 開始可以使用類數組對象。
           

總結:

  • 當我們使用一個函數需要改變this指向的時候才會用到call,apply,bind
  • 如果你想生成一個新的函數長期綁定某個函數給某個對象使用,則可以使用bind
  • 如果你要傳遞的參數不多,則可以使用fn.call(thisObj, arg1, arg2 ...)
  • 如果你要傳遞的參數很多,則可以用數組将參數整理好調用fn.apply(thisObj, [arg1, arg2 ...])

如何手動實作bind、call、apply? 

myBind的實作:

Function.prototype.myBind = function() {
    var _this = this;
    var context = [].shift.call(arguments)
    var args = [].slice.call(arguments)
    return function() {
        return _this.apply(context, [].concat.call(args, [].slice.call(arguments)));
    }
}
           

myCall的實作:

Function.prototype.myCall = function(context) {
    var context = context || global
    context.fn = this
    var arr = []
    for (var i=0,len=arguments.length;i<len;i++) {
        arr.push("arguments[" + i + "]")
    }
    var result = eval("context.fn(" + arr.toString() + ")")
    delete context.fn;
    return result;
}
           

myApply的實作:

Function.prototype.myApply = function(context, arr) {
    var context = context || global
    context.fn = this
    var result
    if (!arr) {
        result = context.fn()
    } else {
        var args = [];
        for (var i=0,len=arr.length;i<len;i++) {
            args.push("arr[" + i + "]")
        }
        result = eval("context.fn([" + args.toString() + "])")
    }
    delete context.fn;
    return result
}
           

bind,call,apply大概就是這麼多介紹,忘指導。。。。

繼續閱讀