1. 程式人生 > 其它 >call、apply、bind實現原理

call、apply、bind實現原理

語法

method.call(obj , argument1 , argument2...)
method.apply(obj , [argument1,argument2..])
method.bind(obj , argument1 , argument2...)

區別

相同點
  1. 三者都可以改變函式內部this的指向
  2. 三者第一個引數都是this要指向的物件,如果引數為空、undefined、null,預設指向window
不同點
方法 引數 是否立即執行
call 第二個引數之後,傳遞的是引數列表
apply 第二個引數是陣列
bind 第二個引數之後,可分多次傳入 ×

作用

  1. 改變引數傳入方式
let arr = [1,2,3,4]
Math.max.apply(null, arr);  // 4
  1. 擴充作用域, 實現物件和屬性之間的解耦
var color = 'red';
var obj = { color : 'blue'};
function showColor(){
    alert(this.color);
}

showColor();  //red
showColor.call(window);  //red
showColor.call(obj);  //blue

原始碼實現

call
Function.prototype.call = function (context, ...args) {
    // 繫結物件為null時,預設指向window物件
    context = context || window
    context.fn = this
    let res = context.fn(...args)
    // 呼叫結束後,刪除物件上新增的方法
    delete context.fn
    // 返回執行方法的結果
    return res
}
apply
Function.prototype.apply = function (context, arg) {
    // 繫結物件為null時,預設指向window物件
    context = context || window
    context.fn = this
    let res = arg ? context.fn(...arg) : context.fn()
    // 呼叫結束後,刪除物件上新增的方法
    delete context.fn
    // 返回執行方法的結果
    return res
}
bind
Function.prototype.bind = function (context, ...arg1) {
    let _this = this
    return function (...arg2) {
        // 組合引數
        let arg = arg1.concat(arg2)

        // 繫結物件為null時,預設指向window物件
        context = context || window
        context.fn = _this
        let res = context.fn(...arg)
        // 呼叫結束後,刪除物件上新增的方法
        delete context.fn
        // 返回執行方法的結果
        return res
    }
}