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

給object定義method

在Javascript中,可以給對象直接定義方法:

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

與傳統(tǒng)的面向?qū)ο笳Z言不同的是,這里不需要在類定義中定義一個(gè)對象的方法。這個(gè)說法倒也有例外的地方,比如說在Ruby中可以給某個(gè)對象(而不是類)定義方法:

 # 定義Rabbit類
 class Rabbit; end

 whiteRabbit = Rabbit.new
 fatRabbit = Rabbit.new

 # 定義對象whiteRabbit的方法speak
 def whiteRabbit.speak(saying)
      puts saying
 end

 whiteRabbit.speak(“天生麗質(zhì)嘿!”)     # works
 fat.speak(“已經(jīng)放棄治療...”)               # NoMethodError: undefined method `speak' for #<Rabbit:0x007ff48bcffda0>

但是像在C++和Java這樣的語言中就不行。

apply的作用

首先澄清函數(shù)方法的區(qū)別,函數(shù)是命令式編程的概念,其不需要綁定在某個(gè)對象上;方法是面向?qū)ο缶幊痰母拍?,需要與一個(gè)對象相綁定。

在函數(shù)式編程中,函數(shù)(代碼片段)是一個(gè)獨(dú)立概念,我們既然可以將其當(dāng)做值傳入傳出,自然也可以將其與任意對象綁定。apply實(shí)現(xiàn)綁定這個(gè)操作,綁定之后,可以利用this指針引用被綁定對象。例子如下:

 // 定義speak這個(gè)函數(shù)
 function speak(line) {
      print("The ", this.adjective, " rabbit says '", line, "'");
 }

 // 直接將speak函數(shù)設(shè)置為whiteRabbit的speak屬性,然后其就成為方法了
 var whiteRabbit = {adjective: "white", speak: speak};
 whiteRabbit.speak("Oh my ears and whiskers, how late it's getting!”);

 // 動態(tài)綁定speak到fatRabbit上,第一個(gè)參數(shù)是被綁定對象,第二個(gè)參數(shù)是一個(gè)Array,傳speak的參數(shù)
 var fatRabbit = {adjective: "fat”};
 speak.apply(fatRabbit, [“Yum”]);
 fatRabbit.speak("I could sure use a carrot right now.”);

call的作用

和apply類似,只是第二個(gè)參數(shù)不再要求是Array,可以是變參。例如:

 speak.call(fatRabbit, “Yum”);

Ruby中的binding

Ruby中的binding基本用不到,它能夠?qū)ontext當(dāng)做變量傳入傳出,例如:

 class Demo
      def initialize(secret)
           @myLittleSecret = secret
      end

      def get_binding
           # binding是個(gè)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的區(qū)別是沒辦法做動態(tài)的方法與對象綁定。但事實(shí)上,它可以做到源碼級別的代碼片段與環(huán)境上下文,其靈活性是遠(yuǎn)遠(yuǎn)超過前述綁定的。例如我們完全可以把函數(shù)的調(diào)用直接用字符串寫進(jìn)去,有神器eval幫我們做解析執(zhí)行即可。

參考:
[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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容