zoukankan      html  css  js  c++  java
  • javascript中apply方法

     明白一点其实就是更改对象的内部指针,即改变对象的this指向的内容。这在面向对象的js编程过程中有时是很有用的。

    call函数和apply方法的第一个参数都是要传入给当前对象的对象,及函数内部的this。后面的参数都是传递给当前对象的参数。

    对于apply和call两者在作用上是相同的,但两者在参数上有区别的。
    对于第一个参数意义都一样,但对第二个参数:
    apply传入的是一个参数数组,也就是将多个参数组合成为一个数组传入,而call则作为call的参数传入(从第二个参数开始)。

    如 func.call(func1,var1,var2,var3)对应的apply写法为:func.apply(func1,[var1,var2,var3])

    同时使用apply的好处是可以直接将当前函数的arguments对象作为apply的第二个参数传入。


    (reference:http://www.cnblogs.com/beyondnet/archive/2007/12/06/985216.html)

    TEST:

    function cls1()
    {
       this.b='111';
       this.c ='222';
       this.d ='333';
       this.f = function()
       {
           alert("nihao");
    }
    }

    function cls2()
    {
       this.a='aaa';
      
       cls1.apply(this); //这里用的是类(也可直接看成函数)直接来apply的。不是用实例。此时,cls2类拥有                                cls1类的所有属性和方法.
      
    }
    var st = new cls2();

    alert(st.d);

    /*注意,这里可以在第2个类中,用第一个类的名称来实现所有属性和方法的复制。方法可以用如下方法复制:ss.f.apply(this);可以正常运行。而属性ss.c.apply(this);则会报错,

    function cls2()
    {
       this.a='aaa';
       var ss = new cls1;
       ss.c.apply(this); //这里会报错。如果为ss.f.apply(this);则正确。如果是属性,则用类名,如果是方法, 即                                     可用类名,也可用实例加方法的形式应该(var ss = new cls1;ss.f.apply(this);)

    如下形式(***正确****)。
      
    }
    var st = new cls2();

    alert(st.c);

    ****正确*******
    function cls2()
    {
       this.a='aaa';
      
       cls1.apply(this); //如果是属性,则用类名,如果是方法,即可用类名,也可用实例加方法的形式

    }

    var st = new cls2();

    alert(st.c);

    _______________________________________________

    function simpleApplyDemo(sim) {
    this.sim_name = sim;
    }
    function handleSPA(hand) {
        this.hand_name = hand ;
    simpleApplyDemo.apply(this, new Array('222222222222'));   //这里用的是类名

    ////此处用Array()数组,是将这个数组的初始化值赋给simpleApplyDemo函数中的参数。也就是sim = 222222222222,在JS手册中,apply([thisObj[,argArray]])的argArra是可选项,解释为将被传递给该函数的参数数组。(也就是说argArray同下的arguments是一样的)

    alert(this.sim_name);
    }                     

    handleSPA();

    上面的方法和下面的方法实现的效果一样

    function simpleApplyDemo(sim) {
    this.sim_name = sim;
    }
    function handleSPA(hand) {
        this.hand_name = hand ;
    simpleApplyDemo.apply(this,arguments);   //这里用的是类名

    /* 此处用arguments,是将handleSPA('55555555')中5555555作为arguments(arguments代表本身的参数 的集合,此处只代表5555555)将arguments传到simpleApplyDemo()中,也就是sim = arguments =55555 */


    alert(this.sim_name);
    }                     

    handleSPA('55555555');

    call方法在msdn中的解释   调用一个对象的一个方法,以另一个对象替换当前对象。

    apply方法在msdn中的解释 应用某一对象的一个方法,用另一个对象替换当前对象。

    这个解释也是非常抽象的,这两个方法的作用基本是一样的,举个例子

    <script>
    function cls1()
    {
       this.a='123';
    }
    cls1.prototype.fun1=function()
    {
       alert(this.a);
    }
    function cls2()
    {
       this.a='456';
    }
    var o1=new cls1();
    var o2=new cls2();
    o1.fun1.apply(o2); //这里用的是实例名,如果写成 o1.apply(o2)则报错
    </script>

    只有o1对象的类cls1中有fun1这个方法,但是,这时我们需要用o2对象替代o1对象,所以这个时候显示的this.a会是456,呵呵很神奇吧,换成call方法也是一样的,这两种方法使用的不同点仅仅是参数的使用方法上不同,这里就不多做解释了。

    大家可以在prototype.js里看到
    var Class = {
       create: function() {
         return function() {
           this.initialize.apply(this, arguments);
         }
       }
    }
    这种代码,相当的夸张,很多人很容易被这种bt的代码弄糊涂,其实仔细分析其中的道理却也不难

    显然这种写法代表了Class是声明的一个Object对象,其中create是这个object对象的一个属性,这个属性就是一个函数。这个函数执行过后返还一个函数。可能这样解释太复杂了,那不如做一个试验好了。

    <script>
    var x=function(){return function(){alert(123);}}
    var n=x();
    n();
    </script>
    很好玩吧,这里n就是x函数执行过后返还给的一个函数也就是n现在等于了function(){alert(123);}再执行n()的时候就跳出了123

    现在开始讲难点 this.initialize.apply(this, arguments);

    这句表达了什么含义,其实现在先看看prototype.js里怎么调用的就明白了

    var Template = Class.create();

    Template.prototype = {
       initialize: function(template, pattern) {
         this.template = template.toString();
         this.pattern   = pattern || Template.Pattern;
       },....省略代码若干

    var template = new Template(replacement);

    第一句话Class.create(); 就是返还给Template 一个函数,这个函数是
    function() {
           this.initialize.apply(this, arguments);
         }
    当执行var template = new Template(replacement);时,就变成了要执行这个函数,而这个函数的作用是
    执行当前类中initialize这个函数

    所以prototype.js中的每一个类都预留了
    Template.prototype = {
       initialize: function(template, pattern) {
         this.template = template.toString();
         this.pattern   = pattern || Template.Pattern;
       },....
    这么个函数,如果没有这个的话,程序将会出错

    知其然,知其所以然,为什么要这么写呢?

    一般我们声明的时候funciton fun(){} var o=new fun();这样感觉fun又是类又是构造函数很别扭,为了分开这种不是很友好的代码方案,所以prototype.js使用了如上方法

  • 相关阅读:
    项目管理理论与实践(6)——利用Excel制作项目文档的设计技巧
    项目管理理论与实践(5)——UML应用(下)
    【工具推荐】ELMAH——可插拔错误日志工具
    ExtJs实践(1)——Ext.extend的用法
    设计一套基于NHibernate二级缓存的MongoDB组件(上)
    ExtJs实践(3)——xtype名称与控件对应
    项目管理理论与实践(2)——软件需求分析
    【培训稿件】构建WCF面向服务的应用程序(包含ppt,源代码)
    ExtJs实践(5)——解决在GridPanel中使用bbar或者tbar的分页条的宽度自适应问题
    项目管理理论与实践(3)——如何进行有效的项目管理
  • 原文地址:https://www.cnblogs.com/lilyzhang/p/1577981.html
Copyright © 2011-2022 走看看