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使用了如上方法

  • 相关阅读:
    BFS visit tree
    Kth Largest Element in an Array 解答
    Merge k Sorted Lists 解答
    Median of Two Sorted Arrays 解答
    Maximal Square 解答
    Best Time to Buy and Sell Stock III 解答
    Best Time to Buy and Sell Stock II 解答
    Best Time to Buy and Sell Stock 解答
    Triangle 解答
    Unique Binary Search Trees II 解答
  • 原文地址:https://www.cnblogs.com/lilyzhang/p/1577981.html
Copyright © 2011-2022 走看看