2

次の (coffeescript) 例では、詳細プロパティを持つ Person クラスを取り上げます。このクラスには、独自のプロパティがあります。

class Person
  constructor: ->
    details =
      name: ''
      age: 0

    Object.defineProperty this, 'details',
      enumerable: yes
      get: => details
      set: (value) =>
        console.log 'set details:', value
        details = value

p = new Person

# does NOT trigger details set()
p.details.name = 'Simon'

# DOES trigger details set(), but takes a bit of effort...
details = p.details
details.name = 'Someone else'
p.details = details

もちろん、name と age を Person クラスのプロパティとして定義すれば、この問題は回避できますが、これは単なる例です。

プロパティが変更されたときに詳細 set() メソッドを起動させる簡単な方法はありますか?

4

1 に答える 1

2

あまり。少なくとも単純ではありません。

pとは全く別物ですp.details。変更p.detailsしても何も変わりませんp。そのため、メッセージが届きません。

あなたがしなければならないことは、自身のプロパティが変更されたときに詳細オブジェクトがその親にメッセージを送信するコードをインストールすることです。これは、親が何であるかを知る必要があることも意味します。

class Person
  constructor: ->
    details =
      name: ''
      age: 0

    Object.defineProperty this, 'details',
      enumerable: yes
      get: -> details
      set: (value) ->
        console.log 'set details:', value
        details = value

        # set parent object to tell when something changes
        value._parent = this

        # create a name setter, which tells it's parent when it changes.
        Object.defineProperty details, 'name',
          enumerable: yes
          get: -> @_name
          set: (value) ->
            @_parent.didUpdateDetails()

     # trigger setter to install hook
     @details = details

   didUpdateDetails: ->
     console.log 'Updated details!'

p = new Person
p.details.name = 'Alex'
# logs: "Updated details!"

そして、ええ、それは本当にうまくいきます: http://jsfiddle.net/PkyaU/1/

しかし、正直なところ、それは少しクレイジーです。これがあなたがする必要があることだと確信していますか?たぶん、あなたのアプローチを再考する必要があります。

于 2013-03-07T02:15:40.013 に答える