2013-03-07 24 views
2

以一个Person类与具体属性,又具有其自身的属性以下(CoffeeScript的)例如:的Javascript Object.defineProperty设置方法触发属性更改

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 

很显然,如果我只需将名称和年龄定义为Person类的属性即可避免此问题,但这仅仅是一个示例。

有什么简单的方法让我的细节set()方法在其属性发生更改时触发?

回答

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/

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

相关问题