• apply和call


      这里推荐一本设计模式的javascript书. 《JavaScript设计模式与开发实践》。作者是腾讯大牛曾探。

      我每天都会在里面抽出我受到的理解,作为我的读书笔记。今天就昨天讲的this里面涉及到的call和apply进行书中的讲解。

         Function.prototype.call 和 Function.prototype.apply 都是非常常用的方法。它们的作用一模 一样,区别仅在于传入参数形式的不同。 

      1.apply

        apply 接受两个参数,第一个参数指定了函数体内 this 对象的指向,第二个参数为一个带下 标的集合,这个集合可以为数组,也可以为类数组,apply 方法把这个集合中的          元素作为参数传 递给被调用的函数。

              For Example:

        var func = function( a, b, c ){

          alert ( [ a, b, c ] ); // 输出 [ 1, 2, 3 ]

          };
        func.apply( null, [ 1, 2, 3 ] );

        //参数123放进数组里面作为参数传入func,对应的参数分别 a b c

         2.call 

      call 传入的参数数量不固定,跟 apply 相同的是,第一个参数也是代表函数体内的 this 指向, 从第二个参数开始往后,每个参数被依次传入函数: 

         For Example: 

      var func = function( a, b, c ){

        alert ( [ a, b, c ] ); // 输出 [ 1, 2, 3 ]

      };
      func.call( null, 1, 2, 3 );

         当调用一个函数时,JavaScript 的解释器并不会计较形参和实参在数量、类型以及顺序上的 区别,JavaScript的参数在内部就是用一个数组来表示的。从这个意义上说,apply 比 call 的使用 率更高,我们不必关心具体有多少参数被传入函数,只要用 apply 一股脑地推过去就可以了。   

      call 是包装在 apply 上面的一颗语法糖,如果我们明确地知道函数接受多少个参数,而且想 一目了然地表达形参和实参的对应关系,那么也可以用 call 来传送参数。

      当使用 call 或者 apply 的时候,如果我们传入的第一个参数为 null,函数体内的 this 会指 向默认的宿主对象,在浏览器中则是 window:

      For Example:

      var func = function( a, b, c ){    

         alert ( this === window );    // 输出 true 

      };
      func.apply( null, [ 1, 2, 3 ] );  

      但如果是在严格模式下,函数体内的 this 还是为 null:

      For Example:
      var func = function( a, b, c ){

         "use strict"; alert ( this === null ); // 输出 true

      }
      func.apply( null, [ 1, 2, 3 ] );  

      有时候我们使用 call 或者 apply 的目的不在于指定 this 指向,而是另有用途,比如借用其 他对象的方法。那么我们可以传入 null 来代替某个具体的对象:

      For Example:
      Math.max.apply( null, [ 1, 2, 5, 3, 4 ] ) // 输出:5

         那call和apply具体怎么怎么用的呢?

      1.改变this的指向

          call 这个函数呢,可以理解它本没有任何资产(属性方法),就借助别人的方法。别人好好的调用自己的方法,它横空一脚,自己在人家后面加上 .call,然后传入自己想要的处理的对象。这样,这个对象就用了别人的方法。省事不少,据说,杜鹃鸟就是这样干的,它不孵化小鸟,把蛋放在别的鸟窝里,让别人代为孵化。

      For Example:

        var obj1 = {

       name: "adou1",

        getName: function(){

          console.log(this.name);//adou2

        }

      }

      var obj2 = {

        name: "adou2"

      } 

      window.name = "window_adou";

          var GetName = function(){

        console.log(this.name);//

      }

      obj1.getName.call(obj2);

         GetName();//window_adou;

      GetName.call(obj1);//adou1;

      GetName.call(obj2);//adou2

         在举一个用call修正this的例子:

        document.getElementById("blog").onclick=function(){

        console.log(this.id);//blog

      }//这我们都知道

      假如在一个事件函数中有一个内部函数,在事件内部调用这个函数的时候,this就指向了 window,如下

        

       document.getElementById("blog").onclick=function(){

        console.log(this.id);//blog

        var func = function (){

          console.log(this.id);//undefined

          //为甚指向的是undefined ,上一篇介绍的this的指向的时候,其中一个普通函数的调用,指向的就是全局 ,ES5中定义,这样的指向为undefined

        }

        func();

      }

      修正过来如下:就是把func()换成 func.call(this);//因为func还是在 onclick函数里调用的,this还是指向的是当前的点击对象

      For Example:     

      document.getElementById = (function( func ){

        return function(){

          return func.apply( document, arguments );

         }

      })( document.getElementById );
        var getId = document.getElementById;

        var div = getId( 'div1' );

        alert ( div.id ); // 输出: div1

      2. Function.prototype.bind 

           For Example:  

        Function.prototype.bind = function(){

          var self = this, // 保存原函数

           context = [].shift.call( arguments ), // 需要绑定的 this 上下文

          args = [].slice.call( arguments ); // 剩余的参数转成数组

          return function(){ // 返回一个新的函数

             return self.apply( context, [].concat.call( args, [].slice.call( arguments ) ) ); // 执行新的函数的时候,会把之前传入的 context 当作新函数体内的           this // 并且组合两次分别传入的参数,作为新函数的参数 } };
            var obj = { name: 'sven' };
            var func = function( a, b, c, d ){

                   alert ( this.name ); // 输出:sven

                   alert ( [ a, b, c, d ] )}

                  .bind( obj, 1, 2 );
            func( 3, 4 );//  输出:[ 1, 2, 3, 4 ] 

      3.借用其他对象的方法 (用的更多点)

      这个具体的案例前面已经有讲:再讲一个通过原型添加对象的方法,然后调用的例子

      var A = function (name){

        this.name = name;

      };

      var B = function(){

        A.apply(this,arguments);

        //调用A的时候返回了 name

      };

      B.prototype.getName = function(){

        return this.name;

      };

         var b = new B("adou");

         console.log(b.getName());//adou

       

  • 相关阅读:
    文档撰写思路与排版(hadoop)
    ULUA的简洁用法(二)
    开源cocos2d-x编辑器 qco-editor
    u3d tolua + ZeroBraneStudio远程调试
    ULUA的简洁用法
    OpenGL顶点数据传输速度优化
    在do while语句中使用continue的误解
    cocos2d-x 3D shader的纹理坐标是上下颠倒的
    使用ndk-gdb调试android native程序
    OpenSSL中AES加密的用法
  • 原文地址:https://www.cnblogs.com/adouwt/p/6384613.html
Copyright © 2020-2023  润新知