2

有什么方法可以找出称为手动订阅的可观察属性的名称吗?

淘汰赛中的回调签名是,.subscribe(function(newValue) { ... }) 但是因为我订阅了一个对象的所有可观察属性,所以我希望有一个这样的签名:(function(newValue, propertyName)并且可能是一个旧值......)。

下面的代码摘录显示我试图在属性周围关闭,但它总是出现最后一个扫描的属性。

我怎样才能知道哪个属性被改变了?

this.Data = ko.mapping.fromJS(dataFromServer);

...

ScrollDataItem.prototype.GetInformedOnChange = function () {
    var self = this;
    for(var prop in this.Data) {
        if(self.Data.hasOwnProperty(prop) && prop != "__ko_mapping__") {
            var closureProp = prop;
            self.Data[prop].subscribe(function (newValue) {
                alert("New value is: " + newValue);
                alert("Property that called: " + closureProp);
            });
        }
    }
};
4

1 回答 1

1

你看到这个的原因是因为提升(http://net.tutsplus.com/tutorials/javascript-ajax/quick-tip-javascript-hoisting-explained/)。您声明的closureProp 变量的作用域是GetInformedOnChange 函数。javascript 中的变量总是作用于函数,而不是 aforwhile循环。

让我们来看看你所看到的。

假设 this.Data 中有 2 个属性:FirstName 和 LastName。第一次for(var prop in this.Data)循环时,prop 是 FirstName,因此closureProp 被分配了名字。订阅已设置,但closureProp 尚未用于任何操作,因为您订阅的内容尚未触发。

第二次循环时,closureProp(相同的变量 - 未创建新变量 - 请参阅上面关于提升的链接)分配给 LastName,然后设置对 LastName 的订阅。

然后,假设 FirstName 订阅被触发,您的匿名函数被调用来执行警报。它使用分配给 LastName 的closureProp。

您可以通过添加额外的范围层(即额外的功能)来解决此问题。方法如下:

创建一个新函数来处理提供额外范围层的订阅:

function subscribeWithName(propName, observable) {
    var closureProp = propName;
    observable.subscribe(function(newValue) {
        alert("New value is: " + newValue);
        alert("Property that called: " + closureProp);
    });
}

调用此函数来设置订阅:

for(var prop in this.Data) {
    if(self.Data.hasOwnProperty(prop) && prop != "__ko_mapping__") {
        subscribeWithName(prop, self.Data[prop]);            
    }
}

这是一个小提琴:http: //jsfiddle.net/tlarson/PfaD7/

于 2013-05-16T13:36:14.970 回答