Javascript Object.defineProperty设置方法触发属性更改

时间:2013-03-07 01:59:30

标签: javascript object coffeescript setter ecmascript-5

使用带有详细信息属性的Person类的以下(coffeescript)示例,该属性又具有自己的属性:

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()方法在其属性发生变化时触发?

1 个答案:

答案 0 :(得分:2)

不是真的。至少不是简单的。

pp.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/

但说实话,这有点疯狂。你确定这是你需要做的吗?也许你应该重新考虑你的方法。