Implementation of 'bind' using Closure and 'call, apply'

233 阅读1分钟

bind函数的内部实现:

function bind(fn,obj){
    return function(){
        return fn.apply(obj,arguments);
    }
}
var fun1=bind(fun,obj1);
var fun2=bind(fun,obj2);
fun1();
fun2();

fun1的执行结果是fun内部this指向obj1的执行结果,fun2的执行结果是fun内部this指向obj2的执行结果。

认真思考的读者看完之后也许就会提出疑问: 既然执行结果都是一样的,我们为什么要多费一举,为fun函数添加wrapper function呢,而不是直接就:

fun.apply(obj1);
fun.apply(obj2);

让我们转换一下场景和思路! 我们这么做其实是要解决这个问题: 我们调用callback函数的过程中,因为被调用函数的调用方式被改变了,被调用函数内部的this也发生了变化。

举起一颗小栗子🌰:

var obj={
    a: 1,
    foo: function(){
        console.log(this.a);
    }
};
setTimeout(obj.foo,1000)
// pseudo implementation of setTimeout()
// function setTimeout(fn,delay){
    //...wait
    fn();
}

尽管我们知道fnobj.foo都指向同样的foo函数。但是fn()obj.foo()两种不同的调用方式导致函数内部的this指向不同。

可是setTimeout(fun1,1000)就没有问题啦!显然fun1指向的函数产生了一个闭包,当这个函数执行的时候:

return fn.apply(obj,arguments);
//fn ->fun1 在父函数的scope中找到了fn,
//obj ->obj1 在父函数的scope中也找到了obj.

嘻嘻嘻,完美地利用了call/apply的显式绑定!