mls3590712
mls3590712

Reputation: 820

knockoutjs observable arrays

To simplify the issue I am having I have come up with the following example.

var ViewModel = function() {
this.self = this;


self.test = ko.observableArray([]);
self.test2 = ko.observableArray([]);


self.test2.push('1');
self.test.push({
  'foo':self.test2()
});
console.log('the following console.log should output an object with foo : [1]');
console.log(self.test());


self.test2.push('2');
self.test.push({
  'foo2':self.test2()
});
console.log('this console.log should have two objects, the first one with foo : [1] and the second with foo2 : [1,2]')
console.log(self.test());

};
ko.applyBindings(new ViewModel());

Initially both arrays are empty

test = []
test2 = []

then we push '1' into test2

test = []
test2 = ['1']

then we push a new object into test equal to the current value of test2

test = [ { 'foo' : ['1'] } ]
test2 = ['1']

And then log the current value of test just to check

We then push '2' onto test2

test = [ { 'foo' : ['1'] } ]
test2 = ['1','2']

And then push a new object onto test with test2's current value

test = [ { 'foo' : ['1'] }, { 'foo2' : ['1','2'] }  ]
test2 = ['1','2']

When all is said and done, the console.log on the JS fiddle will show you that what I expected (above) is not what happens at all.

Both console.logs show the following values for test (note that 'foo' has '1','2' which it shouldn't)

test = [ { 'foo' : ['1','2'] }, { 'foo2' : ['1','2'] }  ]

Can anyone help explain this behavior or how to achieve the desired functionality as described?

JSFiddle: https://jsfiddle.net/xLp3jdr7/

Upvotes: 1

Views: 57

Answers (1)

Roy J
Roy J

Reputation: 43899

self.test.push({
  'foo':self.test2()
});

This puts the object (array) contained in self.test2 into the new object. Objects are passed by reference in JavaScript, they are not copied, so when you modify the object later, this composite object is going to appear different.

One common way of getting a (shallow) copy of an array is to slice it:

self.test.push({
  'foo':self.test2().slice(0)
});

This will behave like you expect, as long as the array isn't itself composed of objects that might change.

Upvotes: 1

Related Questions