美文网首页
javascript中的apply和call,及ruby中的bi

javascript中的apply和call,及ruby中的bi

作者: 海皮飞 | 来源:发表于2013-12-14 13:29 被阅读96次

    给object定义method

    在Javascript中,可以给对象直接定义方法:

     whiteRabbit = {}
     whiteRabbit.speak = function(saying) {
          console.log(saying);
     }
    

    与传统的面向对象语言不同的是,这里不需要在类定义中定义一个对象的方法。这个说法倒也有例外的地方,比如说在Ruby中可以给某个对象(而不是类)定义方法:

     # 定义Rabbit类
     class Rabbit; end
    
     whiteRabbit = Rabbit.new
     fatRabbit = Rabbit.new
    
     # 定义对象whiteRabbit的方法speak
     def whiteRabbit.speak(saying)
          puts saying
     end
    
     whiteRabbit.speak(“天生丽质嘿!”)     # works
     fat.speak(“已经放弃治疗...”)               # NoMethodError: undefined method `speak' for #<Rabbit:0x007ff48bcffda0>
    

    但是像在C++和Java这样的语言中就不行。

    apply的作用

    首先澄清函数方法的区别,函数是命令式编程的概念,其不需要绑定在某个对象上;方法是面向对象编程的概念,需要与一个对象相绑定。

    在函数式编程中,函数(代码片段)是一个独立概念,我们既然可以将其当做值传入传出,自然也可以将其与任意对象绑定。apply实现绑定这个操作,绑定之后,可以利用this指针引用被绑定对象。例子如下:

     // 定义speak这个函数
     function speak(line) {
          print("The ", this.adjective, " rabbit says '", line, "'");
     }
    
     // 直接将speak函数设置为whiteRabbit的speak属性,然后其就成为方法了
     var whiteRabbit = {adjective: "white", speak: speak};
     whiteRabbit.speak("Oh my ears and whiskers, how late it's getting!”);
    
     // 动态绑定speak到fatRabbit上,第一个参数是被绑定对象,第二个参数是一个Array,传speak的参数
     var fatRabbit = {adjective: "fat”};
     speak.apply(fatRabbit, [“Yum”]);
     fatRabbit.speak("I could sure use a carrot right now.”);
    

    call的作用

    和apply类似,只是第二个参数不再要求是Array,可以是变参。例如:

     speak.call(fatRabbit, “Yum”);
    

    Ruby中的binding

    Ruby中的binding基本用不到,它能够将context当做变量传入传出,例如:

     class Demo
          def initialize(secret)
               @myLittleSecret = secret
          end
    
          def get_binding
               # binding是个private方法,要这样来暴露
               binding
          end
     end
    
     d1 = Demo.new 142857
     b1 = d1.get_binding
    
     def unlock(o)
          binding = o.get_binding if o.respond_to? :get_binding
          eval(“@myLittleSecret”, binding)
     end
    
     # 把d1的context传过来用用
     unlock(b1)     # => 142857
    

    与Javascript的区别是没办法做动态的方法与对象绑定。但事实上,它可以做到源码级别的代码片段与环境上下文,其灵活性是远远超过前述绑定的。例如我们完全可以把函数的调用直接用字符串写进去,有神器eval帮我们做解析执行即可。

    参考:
    [1] M. Haverbeke, Eloquent JavaScript: A Modern Introduction to Programming. No Starch Press, 2011.
    [2] http://www.ruby-doc.org/core-2.0.0/Binding.html

    相关文章

      网友评论

          本文标题:javascript中的apply和call,及ruby中的bi

          本文链接:https://www.haomeiwen.com/subject/lnfctttx.html