由于之前的答案似乎暗示AngularJS没有为您的问题提供有针对性的解决方案,因此让我使用原生JS提出一个解决方案。
据我所知,如果您想要实现对象的监视器,您将需要某种形式的getter/setter模式(又名
Mutator method)。我不知道任何关于AngularJS的事情,但我非常确定他们也必须使用类似的东西。在JavaScript中实现getter和setter有多种方法(请参见上面链接的维基百科页面),但通常有三个主要选择:
- 使用外部处理程序(完全隐藏内部数据结构的对象,并仅提供用于读取和写入的API)
- 使用Java风格的getSomething和setSomething方法
- 使用ECMAScript 5.1引入的本机JavaScript属性getter和setter
出于某种原因,我看到了更多通过前两种方法来执行它的示例,但另一方面,我看到了一个使用第三种方法构建的相当复杂和美丽的API的示例。我将通过使用Object.defineProperty给您提供一个通过第三种方法解决您的问题的示例:
这个想法是提供一个观察函数,然后作为属性设置器的一部分来调用它:
function watcher(objectIndex, attributeName) {
console.log('map[' + objectIndex + '].' + attributeName + ' has changed');
}
Object.defineProperty有点像以复杂的方式为对象定义属性。因此,当您通常会编写以下代码时
obj.val1 = "foo";
你将编写
Object.defineProperty(obj, 'val1', {
get: function () { },
set: function (newValue) { },
})
比如说,当 obj.val1 被读取或写入时,您可以定义希望执行的操作。这使您有可能在 setter 的一部分中调用您的 watcher 函数:
Object.defineProperty(obj, 'val1', {
get: function () { },
set: function (newValue) {
watcher()
}
})
虽然这似乎是一段相当简单的代码,但你可以使用函数式编程技术和闭包来构建程序,使其实际上并不那么复杂。因此,即使这看起来不像是“AngularJS方式”做事情,手动实现也不会增加太多开销。
以下是针对您问题的完整代码示例:
http://codepen.io/cido/pen/DEpLj/
在示例中,监视器函数被硬编码为数据结构实现的一部分。但是,如果您需要在多个地方重用此代码,则没有任何阻止您使用例如addEventListener风格的挂钩等扩展解决方案。
由于此方法非常使用闭包,因此如果您真的处理大量数据,则可能会有一些内存影响。但是,在大多数用例中,您无需担心这种类型的问题。另一方面,所有基于“深度相等”检查的解决方案都不会超级内存高效或快速。