• 我们在编写js的过程中经常会出现这样的逻辑需要:某个对象临时需要一个方法,用来处理一些业务,而这样的一个方法的逻辑已经在另一个对象的方法里或函数里面定义过了,所以我们可以不用再在这个对象下添加一个相同的方法了!那我们该怎么做呢?我们的逻辑就是调用已经实现了业务需要的方法或者函数,只是把它的上线文改为当前对象就好了,需要灵活使用的两个方法就是apply和call。好了,我们先来看下下面的示例代码吧:
    1. var num = 0;
    2. for(var i = 0,len = arguments.length;i<len;i++){
    3. num += arguments[i];
    4. };
    5. console.log(num);
    6. return num;
    7. };
    8. var arr = [1,2,5,7,78,14];
    9. var arrSum = sum.apply(null,arr);//output 107
    10. var argsSum = sum.call(null,1,2,5,7,78,14);//output 107
    11. //顺表说一句,如果上下文设置null,那么的浏览器中就是window
    • 首先这样做肯定有它的道理的:1、上面的写法很不灵和,因为你每次调用的时候都要写一句—sum.apply(null,…)—,如果只是一次还好,如果你有很多次呢!是不是很烦,我们为什么不能一次性到位;2、其次使用bind的方式,可以保持原有代码风格的情况下实现需求,更利于理解对不;3、当然了还有其它好处,我也暂时没想到,需要集合业务场景说明。总之具体场景具体分析,那种方便就使用那种,又不是板上钉钉的事情!
    • 首先我确实在这上面花了一些时间写出来,什么原因呢?说白了还是对javascript的一些细节不能一下子想通。好,我把我写的用于实现bind函数的每种方式依次说明,并带有代码示例,并说明当时是怎么想的?

    • 第一次我是这样实现的,代码如下:

    1. var _function = this;//用于保留原函数的引用
    2. var _args = Array.prototype.slice.call(arguments,1);//用于取出原函数的参数
    3. _function.apply(content,_args);
    4. };

    好了,第一次总算是把bind的功能实现了,那我们看下怎么用呢?应用如下:

    1. //第二种方式
    2. var _function = this;
    3. return function(){
    4. return _function.apply(content,arguments);
    5. };
    6. };

    我们再来看一下在实际生产中怎么调用:

    1. var surname = '全局';
    2. var name = '变量';
    3. var person = {
    4. surname : '周',
    5. name:'杰伦'
    6. };
    7. var getFullName = function(surname,name){
    8. var fullName = this.surname + this.name;
    9. console.log(fullName);
    10. return fullName;
    11. }.bind(person);
    12. getFullName(surname,name);//output 周杰伦
    13. // var fullName = this.surname + this.name;
    14. // console.log(fullName);
    15. // return fullName;
    16. //};
    17. //getFullName.bind(person)(surname,name);

    恩好,这一次我们实现了保持原有函数调用的熟悉形式,更利于理解对不!

    说明一下从第一种方式到第二种方式经过了怎样的改变:1、我们并没有用slice方法用截断的方式去取得原函数的参数,而是保持了原有函数的代码,这样更灵活、更符合“封闭-开环”原则;2、我们并没有在bind函数内部调用我们的函数,而是返回了一个匿名函数,然后再在匿名函数里面调用我们的函数,这一点很重要,因为它实现了,我们可以不用改变我们原来函数的参数序列。这里需要说明一下,我最开始是没有理解这一点的,因为我理解的是调用原函数时传的arguments是bind函数的参数队列,其实这样理解思路本来是没有问题的,只不过它已经返回了匿名函数,也就是在使用return的时候,arguments就跟bind函数没有关系了,所以这个arguments就是指的原函数的参数队列,理解这一点很重要!为了说明这一点,我们来看下下面的代码:

    • 因为上面的方式在原型上修改的,所以很容易造成冲突,因为很多第三方库,也实现了类似的方式,所以为了避免出现冲突,我们决定实现自己的bind函数,把它作为自己定义的命名空间上的一个方法,类似myNameSpace.bind的形式!但是了我们这里主要讲的函数的实现,所以为了更简单说明问题,我采用了写一个全局函数的方式来实现!
    • 其实这种方式的实现的逻辑跟前面两种方式差不多的,原理是一样的,代码如下:
    1. function bind(content,fn){
    2. return function(){
    3. fn.apply(content,arguments);
    4. };
    5. };

    实际中这样调用就好:

    1. window.name = 'window';
    2. var obj = {
    3. name : 'obj'
    4. };
    5. function getName(){
    6. console.log(this.name);
    7. return this.name;
    8. };

    ok,我们发现上面的代码是可以工作的!至此,我想到的几种实现自定bind函数的方法到此完毕!那么我们来看一下在实际开发中是怎么用的!

    • 实现绑定指定的上下文,示例如下:

    内容待续….