In WinRT, a number of APIs return a Windows.Foundation.Collections.PropertySet object. Two examples are the localSettings and roamingSettings objects within Windows.Storage.ApplicationData.current, whose values propert is a PropertySet.

In JavaScript, doing a simple for…in iteration on a PropertySet will give you not only the properties in that set, but also its methods, which is often unexpected. For example, the following code:

var ls = Windows.Storage.ApplicationData.current.localSettings;
ls.values[“property1”] = “value1”;
ls.values[“property2”] = “value2”;
ls.values[“property3”] = “value3”;

for (var key in ls.values) {
    console.log(“values[“ + key + “] = “ + ls.values[key]);
}

will not only output “values[property1] = value1” for each of the three values, but will also give you stuff like:

values[addEventListener] =
function addEventListener() {
[native code]
}

This comes as a result of how the PropertySet is projected from WinRT into JavaScript. It sort of works like an array, but not really, so you get this kind of behavior.

Seeing this, one option is to use the iteration methods of the PropertySet, meaning to call its first method to obtain an iterator, then using the iterator’s cumbersome current/moveNext semantics. This isn’t particularly enjoyable code to write in my mind.

Fortunately, there’s an easier way, which Luke Hoban provided based on an old blog post by Douglas Crockford, http://yuiblog.com/blog/2006/09/26/for-in-intrigue/, in which he points out that for…in includes all the keys in an object’s prototype and not just those in the object itself. To prevent this, you have to use the hasOwnProperty method to check where the property is coming from. So this modification of the code above will produce the expected output:

for (var key in ls.values) {
    if (ls.values.hasOwnProperty(key)) {
        console.log(“values[“ + key + “] = “ + ls.values[key]);
    }
}

Better still, in Windows Store apps we can rely on the more intelligent behavior of EcmaScript 5’s forEach iterator, and just do the following:

Object.keys(ls.values).forEach(function (key) {
    console.log(“values[“ + key + “] = “ + ls.values[key]);
});

This produces the same results with a simpler construct.


Comments are closed