/*watch individual property*/ $scope.$watch('map[someid].val1',function(new_val,old_val) { //do something }); /*watch entire object,how would this help me?*/ $scope.$watch('map',old_val) { //do something },true);
解决方法
AFAIK如果你想实现一个对象的观察者,你需要某种getter / setter模式(又名.Mutator method).我对AngularJS一无所知,但我很确定他们也必须使用类似的东西.有多种方法可以在JavaScript中实现getter和setter(请参阅上面链接的Wikipedia页面),但一般来说,您有三个主要选择:
>使用外部处理程序(完全隐藏内部数据结构的对象,仅提供用于读写的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) { /* ... */ },// possible other parameters for defineProperty })
IE浏览器.您可以定义在读取和写入obj.val1时要执行的操作.这使您可以将您的观察者功能称为setter的一部分:
Object.defineProperty(obj,set: function (newValue) { // set the value somewhere; just don't use this.val1 /* call the */ watcher(/* with args,of course */) } })
对于非常简单的事情来说,它看起来可能是相当多的代码行,但是您可以使用函数式编程技术和闭包来构建程序,以便编写实际上并不那么复杂.所以从本质上讲,尽管这可能看起来不像是一种“AngularJS方式”,但实际上并不需要太多的开销.
以下是针对您的问题的完整代码示例:http://codepen.io/cido/pen/DEpLj/
在该示例中,观察器功能很难编码为数据结构实现的一部分.但是,如果您需要在多个位置重复使用此代码,那么没有什么能够阻止您使用例如扩展解决方案. addEventListener-时尚钩子等
由于这种方法使用闭包很多,如果你真的处理大量数据,它可能会有一些内存含义.但是,在大多数用例中,您不必担心这类事情.而另一方面,基于“深度相等”检查的所有解决方案也不会是超级内存效率或快速的.