This code uses this
instead of self
in one instance, which will cause unexpected errors.
Regarding arrays: Using an array to store data is not concurrency safe. When multiple users try to push to the same key, one will be overwritten. Instead, use an object and utilize Firebase's push command.
Regarding proper usage of child_added: The documentation for child_added states that there is no differentiation between existing and new records:
Child Added: This event will be triggered once for each initial child at this location, and it will be triggered again every time a new child is added. The DataSnapshot passed into the callback will reflect the data for the relevant child. For ordering purposes, it is passed a second argument which is a string containing the name of the previous sibling child by priority order (or null if it is the first child.)
The point here is to reduce code complexity. We're working in a real-time paradigm; data is in constant flux. There is no need to if/then/else around initial data vs new data vs posted data etc; it doesn't even make a lot of sense for real-time ops.
And finally, answering your question. As you can see from the points above, there is no need to use value in this case:
var Model = function (id) {
var self = this;
self.times = ko.observableArray();
self.ref = firebase.child("users/" + id);
// loads all data at this path, regardless of whether it existed
// before or after I establish this listener
self.ref.on("child_added", self.addChild.bind(self));
self.addChild = function (snapshot) {
self.times.push(snapshot.val());
}
};