2012-04-23 10 views
0

私はクラスベースのOOシステムを使用するC#/ Javaのバックグラウンドから来ていますが、まだJavaScript/CoffeeScriptプロトタイプのOOシステムは取得していません。下のCoffeeScriptクラスを書いたので、システム側の好みに応じて連絡先の名前を表示することができます。私はクラスを動作させるには、joinNonEmpty(stringList, joinText)メソッドをプロトタイプに所属させ、それをJava/C#土地で静的メソッドと呼ぶ方法で呼び出すだけです。私のcoffeescriptメソッドはなぜクラスに属していなければなりませんか?

  1. this.joinNonEmpty(...)を使用してこのメ​​ソッドを呼び出す方法はありますか?
  2. これでコンストラクタ内のfirstLastRender, lastFirstRender and firstOrNickThenLastメソッドを参照できる理由を説明できますか? joinNonEmptyヘルパーに電話するときは、これらの方法では機能しませんか?
  3. これは、私が環境設定マップで適切なメソッドを見つける方法と関係がありますか?答えるために時間を割いて
prefs = displayNameFormat: "FirstOrNickThenLast" 

class DisplayNameRenderer 

    constructor: -> 
     @prefToRenderMap = 
      FirstLast: this.firstLastRender 
      LastFirst: this.lastFirstRender 
      FirstOrNickThenLast: this.firstOrNickThenLast 

    # Why does this method have to be static (a class method)? 
    @joinNonEmpty: (stringList, joinText) -> 
     nonEmptyStrings = [] 
     for s in stringList 
      nonEmptyStrings.push(s) if s isnt null and s isnt "" 
     nonEmptyStrings.join(joinText) 

    firstLastRender: (contact) -> 
     # TypeError: Object expected. 
     joinNonEmpty([contact.firstName, contact.lastName], ' ') 

    lastFirstRender: (contact) -> 
     # TypeError: Object doesn't support this method or property 
     this.joinNonEmpty([contact.lastName, contact.firstName], ', ') 

    firstOrNickThenLast: (contact) -> 
     # Works correctly. 
     DisplayNameRenderer.joinNonEmpty([(if contact.nickname isnt null and contact.nickname isnt "" then contact.nickname else contact.firstName), contact.lastName], ' ') 

    render: (contact) -> 
     @prefToRenderMap[prefs.displayNameFormat](contact) 

contact = firstName: "Jonathan", nickname: "Jonny", lastName: "Appleseed" 

dnr = new DisplayNameRenderer() 

# => "Jonny Appleseed" 
console.log dnr.render(contact) 

感謝。

答えて

4

this(AKA @)は、関数が呼び出されたときに決定されます(例外は以下を参照)。あなたは@prefToRenderMapインスタンス変数に三つの機能に結合していないの参照を保存している

@prefToRenderMap = 
    FirstLast: this.firstLastRender 
    LastFirst: this.lastFirstRender 
    FirstOrNickThenLast: this.firstOrNickThenLast 

@prefToRenderMapはオブジェクトそのものです:だから、これを行うとき。そして、あなたはこのようなあなたのDisplayNameRendererインスタンスのメソッド呼び出ししよう:

@prefToRenderMap[prefs.displayNameFormat](contact) 

をし、方法が間違っている文脈と@で呼ばれているので、すべてが崩壊してしまう彼らはそれがあることを期待しているものではありません。 prefs'FirstOrNickThenLast'であるなら、あなたはこれを効果的にやっている:

@prefToRenderMap.FirstOrNickThenLast(contact) 

@(AKA thisfirstOrNickThenLastメソッドの内部@prefToRenderMapになります。しかし、もちろん、@prefToRenderMapには、さまざまなエラーが発生するように呼び出すメソッドはありません。

一つの解決策は、メソッドを定義するためにfat arrow (=>)を使用することです:

脂肪の矢印=>関数を定義し、適切な場所に、thisの現在の値にバインドするの両方に使用することができます。

joinNonEmpty: (stringList, joinText) -> 
    #... 

firstLastRender: (contact) => 
    @joinNonEmpty([contact.firstName, contact.lastName], ' ') 

を、すべてがうまくいく:

だから、このようなものを持つことができます。

http://jsfiddle.net/ambiguous/RAPJw/1/

ます。また、その名前でメソッドを参照することにより、この問題を回避することができます:ここではまた、あなたのthis問題が表示されますストリップダウンのデモです。文字列にメソッド名m = 'some_method'がある場合、JavaScriptとCoffeeScriptの両方でo[m]()のようにそのメソッドを呼び出すことができます。結果は、o.some_method()と同じです。より良い構造がより次のようになります。

class DisplayNameRenderer 
    constructor: -> 
     @prefToRenderMap = 
      FirstOrNickThenLast: 'firstOrNickThenLast' 

    joinNonEmpty: (stringList, joinText) -> 
     #... 

    firstOrNickThenLast: (contact) -> 
     @joinNonEmpty([(if contact.nickname isnt null and contact.nickname isnt "" then contact.nickname else contact.firstName), contact.lastName], ' ') 

    render: (contact) -> 
     @[@prefToRenderMap['FirstOrNickThenLast']](contact) 

@prefToRenderMapの構造に変更し、それがrenderでどのように使用されますか。そして、このアプローチのデモ:@constructor.class_method():余談としてhttp://jsfiddle.net/ambiguous/DFYwu/


は、代わりにインスタンスメソッド内ClassName.class_method()を言って、あなたは代わりにconstructorプロパティを使用することができます。また、CoffeeScriptではとthis.propertyではなく、@method()または@propertyと表示されます。

+0

これはかなり意味があります、ありがとうございます。私はスコープについて何が起こっているのかを理解しています。 –

関連する問題