search

Home  >  Q&A  >  body text

javascript - 为什么要用return fn.apply(context,arguments)而不是fn(arguments)

fucntion bind(fn,context){
return function(){
return fn.apply(context,arguments);
};
}还有,为什么要返回两次,不能直接返回return fn.applay(context,arguments)? 麻烦老师解答!!

PHP中文网PHP中文网2894 days ago540

reply all(3)I'll reply

  • ringa_lee

    ringa_lee2017-04-10 17:32:14

    首先你要搞清楚bind这个函数的含义。它的输入(即参数)是一个函数,输出(即返回值)也是一个函数。它不会去调用函数,只是处理函数。不太严格的说就是:它把某个对象context绑定到了函数fn身上,使得fn后续被调用时this总是context这个对象。

    如果改成你说的那样,首先bind的返回值就不是一个函数了,其次bind就不是在处理(即重新封装)函数了,而变成了直接调用fn并将返回值作为返回值返回了。这样的话,语义完全就不对了!

    至于为什么用apply而不是用fn(arguments),那是因为需要用context来给fn指定this,这正是只有applycall才能完成的工作。如果用fn(arguments)的话,函数调用时的this会变成undefinedwindow

    至于为什么返回两次。其实没有返回两次,第一个return是内部函数返回的。写成下面这样可能好理解一些:

    fucntion bind(fn, context) { 
        var fn2 = function(){
            return fn.apply(context,arguments); 
        };
        
        return fn2;
    }

    reply
    0
  • 伊谢尔伦

    伊谢尔伦2017-04-10 17:32:14

    bind函数主要是用于事件处理程序和settimeout和setInterval,在三种情况中,回调函数中的this指向的是当前对象,要是不用bind()绑定的话,那么当外部有一个对象采取对象字面量方式封装了变量和方法便无法正确地调用,不知道这样理解对不对呢?

    reply
    0
  • 阿神

    阿神2017-04-10 17:32:14

    这个函数就相当于

    fucntion bind(fn, context) { 
        var fn2 = function(){
            return fn.apply(context,arguments); 
        };
        return fn2;
    }

    在JavaScript中,函数是first class即头等公民,它可以被赋值给一个变量、可以当作参数、可以作为返回值。

    然后在来看看这个函数做了什么?

    // 在非严格模式下
    // 正常情况下,test内的this是指向window的
    function test(){
        console.log(this);
    }
    
    test();// window
    
    // 因为bind返回的是一个函数,所以我们要接收这个返回值
    
    var fn = bind(test,window);
    
    // 返回值是一个函数,所以我们可以执行它
    
    fn(); // window
    
    // 如果我们把第二个参数传成我们自己定义的对象呢?
    
    var obj = { name:"pod2g",age:26 };
    
    var fn2 = bind(test,obj);
    
    // 此时test内部的this就不再指向window,而改为指向obj了 
    
    fn2();// Object {name:"pod2g",age:26}
    
    

    从上面的2个例子我们可以看出来,bind函数是用来改变被传入函数内部的this指向的,既然改变,你总得给我一个新的指向吧?好,第二个参数闪亮登场,他就是第一个参数内部this的新指向。。。

    为啥要这么做呢?

    假设说,有一个对象,有一个sayNameAfterOneSecond方法,执行他之后,在1秒后弹出我的名字(我是个帅比)。。

    
    // 假设说,全局有一个丑比
    
    var name = "丑比"
    
    var obj = {
        name:"帅比",
        age:26,
        sayNameAfterOneSecond:function(){
            setTimeout(function(){
                console.log('I am '+ this.name);
            },1000)
        }
     }
    
     // 丑比多作怪啊。。。
    
     obj.sayNameAfterOneSecond(); // I am a 丑比
    
    

    如何如愿以偿地弹出我的名字而不是全局对象name的值呢?。。

    sayNameAfterOneSecond:function(){
            // 把setTimeout的函数内部的this指向为obj对象,而不是指向全局window对象。。
            setTimeout(bind(function(){
                console.log('I am '+ this.name);
            },this),1000);
        }
         // 哈哈,改变之后,就真实地弹出来我的名字。。
         obj.sayNameAfterOneSecond(); // I am a 帅比

    bind函数,一言以蔽之,就是为了改变函数内部this指向的。。。

    PS:原生也有bind函数。。Function.prototype.bind

    reply
    0
  • Cancelreply