2013-03-07 42 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/

但說實話,這是一個有點瘋狂。你確定這是你需要做的嗎?也許你應該重新考慮你的方法。

相關問題