javascript中bind多次绑定和apply,call,bind同时使用的深入理解

之前在看angualr的源码,看到一个很奇怪的写法,当时只是大概懂意思,也没深入研究,最近有时间深入研究了下,然后把自己的分析和理解记录下来。

1.当bind,call或者apply同时使用

先看一段angualr的源码:

 function instantiate(Type, locals, serviceName) {
        // Check if Type is annotated and use just the given function at n-1 as parameter
        // e.g. someModule.factory('greeter', ['$window', function(renamed$window) {}]);
        var ctor = (isArray(Type) ? Type[Type.length - 1] : Type);
        var args = injectionArgs(Type, locals, serviceName);
        // Empty object at position 0 is ignored for invocation with `new`, but required.
        args.unshift(null);
        return new(Function.prototype.bind.apply(ctor, args))();
}

这个代码的逻辑不需要理解(angualr实例化服务,以后的文章我会解释),你只需要看后面2行代码就可以,代码中ctor是个函数,args是个数组,它把null值放到数组的第一个位置,相当于[null,…],然后return出来一个实例,是不是看起来很迷糊,Function.prototype.bind.apply,又bind,又apply?,啥意思啊,前面有个new肯定知道是实例化对象来的,上一篇文章我说了apply,call,bind的底层实现,不懂的同学可以点击这里。这段代码到底在做什么呢,其实它是把数组形参(我不知道有多少个形参时候用apply),传入到ctor函数中,具体的说,就是向构造函数中先传入参数,然后再实例化出来。下面我来一一分析它的实现原理:
1."Function.prototype.bind"如果你不改写,这个是所有的函数都有的方法,可以把"Function.prototype.bind"当成一个函数。
2."apply"改变了this的指向。
3."args"数组形参的传入。
相当于: “函数.apply(函数,形参)”,那么上面那段代码就可以改成这样 “ctor.bind(null,…)”,bind是返回一个新的函数。
来看个理解加深下理解吧:

 function Person(){
     this.name = arguments[0];
     this.age = arguments[1];
     this.sex=arguments[2];
 }
 var p =  Function.prototype.bind.apply(Person,[null,'zhangsan','18','man']); 
 // var p = Person.bind(null,'zhangsan','18','man');
 var p1 = new p();
 console.log(p1.name,p1.age,p1.sex); //zhangsan 18 man

“Function.prototype.bind.apply(Person,[null,‘zhangsan’,‘18’,‘man’]) " 可以改写成 “Person.bind( null , ‘zhangsan’ , ‘18’ , ‘man’ )”
这就是为什么要把null放在数组的最前面。可能有些同学会说这样写不也可以?“Function.prototype.apply.bind(Person,[null,‘zhangsan’,‘18’,‘man’]); " 这样些肯定是不行的,改写之后” Person.apply( [null , ‘zhangsan’ , ‘18’ , ‘man’] )” ,这样函数就执行了,你再new就会报错了。所以"Function.prototype.bind.apply"可以解决实例化构造函数传入未知形参的问题。

2.当bind多次绑定

先上段测试代码:

 function foo() {
     console.log(this.value);
 };

 obj = {
     value: 10
 };
 obj1 = {
     value: 100
 };
 obj2 = {
     value: 1000
 };
 var p = foo.bind(obj).bind(obj1).bind(obj2);
 p();//10

为什么会是10,bind 绑定之后会返回新的函数,所以代码我们可以看成 ‘新函数’.bind(obj2),这个’新函数’里面还有’新函数’,‘新函数’里面还有’新函数’,知道有这些的话,我们只看最外层的一个就好了,当 p()之后此时最外层的’新函数’的this指向是obj2(1000),然后接着执行里面的’新函数’,接着this从obj2(1000)指向了obj(100),一直这样,最后执行到foo.bind(obj),此时this已经指向obj(10)了,所以输出的结果是10,原理很简单,多次绑定bind只是一直在改变this的指向,最终还是变回第一次绑定的this。所以bind多次绑定是无效,只有第一次有效果。好了,到这里就差不多已经说完了(如果有不对之处,欢迎指正,不胜感激!!!),欢乐的时光总是过得特别快,又到时候和大家讲拜拜!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值