属性更改时Javascript Object.defineProperty set方法触发器
以下面的(coffeescript)示例为例,它是一个具有details属性的Person类,而details属性又有自己的属性:属性更改时Javascript Object.defineProperty set方法触发器,javascript,object,coffeescript,setter,ecmascript-5,Javascript,Object,Coffeescript,Setter,Ecmascript 5,以下面的(coffeescript)示例为例,它是一个具有details属性的Person类,而details属性又有自己的属性: class Person constructor: -> details = name: '' age: 0 Object.defineProperty this, 'details', enumerable: yes get: => details set: (value
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类的属性,我可以避免这个问题,但这只是一个示例
有什么简单的方法可以让my details set()方法在其属性发生更改时启动吗?没有。至少不简单
p
与p.details
完全不同。修改p.details
根本不会改变p
的任何内容。所以它不会收到信息
您需要做的是安装一些代码,使details对象在其自身属性更改时向其父对象发送消息。这也意味着它需要知道它的父对象是什么
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!"
是的,这真的很有效:
但老实说,这有点疯狂。你确定这就是你需要做的吗?也许你应该重新考虑你的方法