Backbone.js: Model inheritance causes shared data - javascript

I've been banging my head on this one for the last two days. For some reason backbone is sharing parent instance data across inherited child models. Heres an example:
var Base = Backbone.Model.extend({
index : []
});
var Group = Base.extend({
initialize : function() {
this.index.push('from group');
}
});
var User = Base.extend({
initialize : function() {
this.index.push('from user');
}
});
var user = new User();
console.log(user.index); // ['from user']
var group = new Group();
console.log(group.index) // ['from user', 'from group']
What I'm looking for is:
console.log(user.index); // ['from user']
console.log(group.index) // ['from group']
Any insights?
Thanks!
Matt

What you are experiencing is essentially a byproduct of the way JS passes objects (or arrays) by reference and not by value. If you want index to be different for User and Group, simply instantiate it as an array in your initialize function.
var Base = Backbone.Model.extend({
initialize: function() {
this.index = [];
}
});

The index member is like a class variable in that it's in the prototype chain of Base and thus shared by all instances just as the methods it contains are also shared. Try switching the order of the instantiating User and Group. Now what does index contain? It's reverse right? That's because they are sharing everything the object passed to extend.
In order for it to be an instance variable you'll need to instantiate it in a constructor for Base, and have each subclass call that constructor from their respective constructors. Like:
var Base = Backbone.Model.extend({
initialize: function() {
this.index = [];
}
});
var User = Base.extend({
initialize: function() {
Base.prototype.initialize.call( this );
this.index.push('User');
}
});
// repeat it for group.

Related

How to bind a function with sub-observables to an observable array?

I have following ViewModel:
var Order = function(data) {
this.fruits = ko.observableArray(ko.utils.arrayMap(data.Fruis, function(item) { return item; }));
this.vegetables = ko.observableArray(ko.utils.arrayMap(data.Vegetables, function(item) { return item; }));
};
I need to define some sub-properties and sub-observables bound to the specific instance, and some common methods for fruits and vegetables,:
var Items = function(data, type) {
var self = this;
self.type = type;
self.choice = ko.observable(-1);
self.choice.select = ko.computed(function(){
var id = self.choice();
// do stuff
});
self.choice.remove = function() {
var id = self.choice.peek();
// do stuff
};
self.add = function(code) {
//do stuff
self.choice(id);
};
};
Which is the right way to bind the function containing my set of methods and sub-observables, so that i can use the methods as follows:
orderViewModel.fruits.add("apples");
orderViewModel.fruits.add("bananas");
orderViewModel.fruits.choice(0);
orderViewModel.fruits.choice.remove();
console.log(ko.tpJSON(orderViewModel));
// prints: {fruits: [bananas], vegetables: []};
I think there is no need to use extenders, as the properties and methods aren't generic, and don't need to be common to all observables.
I tried by returning an observable array from my Item function, but i wasn't able to get this to work, as sub-properties and sub-observables have been lost. How can i bind Items to my observable arrays?
Even though you might not want to create an extender, what you're doing here is extending an observable array...
If you don't want to register an extender, you can create a small helper function to create an observableArray and add some methods and properties to it before you return.
In the example below you can see some example code. Some important advice:
If you use this approach, I'd suggest not overwriting the default methods in observableArray. E.g.: remove takes an item by default; you want it to work with an external choice index... It's best to pick a different name so you keep supporting both.
If you end up using the extension a lot, it might be worth it to create a clean viewmodel that stores the observable array internally. You can define a toArray method for exporting to a plain array.
var obsCollection = function(initialItems) {
var items = ko.observableArray(initialItems);
items.choice = ko.observable(-1);
items.add = items.push;
var ogRemove = items.remove.bind(items);
// I'd rename this to "deleteChoice"
items.remove = function() {
var index = items.choice();
ogRemove(items()[index]);
// Reset choice to -1 here?
};
return items;
};
var fruits = obsCollection(["Apple"]);
log(fruits);
fruits.add("Banana");
fruits.choice(0);
fruits.remove();
log(fruits);
fruits.remove();
fruits.add("Mango");
fruits.add("Lemon");
log(fruits);
function log(d) {
console.log(JSON.stringify(ko.unwrap(d)));
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
Edit to clarify the (lack of) use of this:
Since we don't use the new keyword, there's no real need to use this. Internally, the observableArray creates a new instance, but our only way of referring to this instance is through items. When detaching prototype methods from the array, we need to make sure we call them with the right context, by either bind or .call(items) (or apply).
If you want the code to look like a "class", you can either do: var self = items; and continue with the self keyword, or rewrite it to use the new keyword (last bullet point in my answer).
var myArray = ko.observableArray([1,2,3]);
try {
// Reference the function without binding `this`:
var removeFromMyArray = myArray.remove;
// Internally, the observableArray.prototype.remove method
// uses `this` to refer to itself. By the time we call it,
// `this` will refer to `window`, resulting in an error.
removeFromMyArray(2);
} catch(err) {
console.log("ERROR:", err.message);
console.log(myArray());
}
// By binding to the array, we ensure that the function reference
// is always called in the right context.
var boundRemoveFromMyArray = myArray.remove.bind(myArray);
boundRemoveFromMyArray(2);
console.log(myArray());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

Accessing properties in parent class

I am trying to make a parent data access layer class that is inherited by multiple classes.
parent class:
var DataAccess = function() {
this.Save = function(){
alert(this.ListName); //works
SaveLogic(this.Id); //doesnt work
}
}
Child Class:
var Job = function(){
Job.prototype.ListName = 'MyList'; //works
this.Save = function(){
Job.prototype.Save().call(this);
//specific Job Save logic
}
}
Job.prototype = new DataAccess();
Now in my main class:
var aJob = new Job();
aJob.Id = 1;
aJob.Save(); //Does not work. Prototype can not see aJob.Id..
As you can see, I need to create a parent function with shared variables such as ID, so when I inherit the parent class, I can assign values to these variables so the shared logic of hte parents class work, then my extended class's can have specific logic
You can start with construction like this:
var DataAccess = function() {
this.Save = function(){
console.log('DataAccess Save call', this.ListName, this.Id);
}
}
var Job = function(){
this.ListName = 'MyList';
}
Job.prototype = new DataAccess();
/**
* Delete me to use parent's Save method.
*/
Job.prototype.Save = function(){
console.log('Job Save call', this.ListName, this.Id);
}
var aJob = new Job();
aJob.Id = 1;
aJob.Save();
#stivlo described how it works in his answer here: https://stackoverflow.com/a/4778408/1127848
The problem I had was I wanted to reuse the same code. I think I have worked it out this way, im still not 100% its the right way to go with prototype programming :
function DataAccess() {
//setup common variables
}
DataAccess._Save_(listname, id){
commonSaveLogic(id);
doStuff(listname);
}
function Job() {
this.ListName = 'Jobs';
DataAccess.call(this); //call DataAccess Constructor
}
Job.prototype = DataAccess;
Job.prototype.constructor = Job;
Job.ProtoType.Save = function(){
this._Save_(this.ListName, this.Id);
}
function AotherList() {
this.ListName = 'AnotherList';
DataAccess.call(this);
}
//same as above. Job and Another list both inherit off DataAccess.
Dont use .prototype inside the constructor. We define .prototype for sharing same copy to all objects.
You are missing here many things. I'm explaining one by one:
First : SaveLogic(this.Id); //doesnt work
Because You don't use this with the function so it's a global function not a constructor function. And you don't have defined it any where so there will be an error like function SaveLogic not defined
To prevent this error, define the function somewhere.
Second : You have passed this.Id as a parameter. Id using the line aJob.Id = 1; will not be accessible within the SaveLogic(this.Id); because Id is a property of aJob not of ajob.prototype. this.ListName will be available here because it's a property of prototype.
So it you want to get Id inside SaveLogic() function, define it as prototype property.
Third : when this line aJob.Save(); will be invoke it will call
this.Save = function(){
Job.prototype.Save().call(this);
//specific Job Save logic
}
Job.prototype.Save() will search for a function named as Save(). Which is not defined in Job's prototype so function not defined error will occur.
Fourth : call() can not be called anyhow excepts either DataAccess.call() or Job.call();
call() is just like the constructor call excepts it's first parameter get assigned to the constructor's this object.
Here i have improved your code. Just copy and paste it in your editor and see what is going here.
Try this :
function SaveLogic(Id)
{
alert(Id);
}
var DataAccess = function() {
this.Save = function(){
alert(this.ListName); //works
SaveLogic(this.Id);
return this; //doesnt work
}
this.call = function() {
alert('call is called here');
}
}
var Job = function(){
Job.prototype.ListName = 'MyList'; //works
this.Save = function(){
//console.log(Job.prototype.Save());
Job.prototype.Save().call(this);
//specific Job Save logic
}
}
Job.prototype = new DataAccess();
var aJob = new Job();
Job.prototype.Id = 1;
aJob.Save(); //Does not work. Prototype can not see aJob.Id..

How to create new instance of parent class in javascript

I have a class that inherits from another. Within the base class, I'm wondering if it is possible to create and return a new instance of the calling parent class.
Here's an example:
Base:
var util = require('util');
var ThingBase = function(options) {
}
ThingBase.prototype.mapper = function(data) {
// do a bunch of stuff with data and then
// return new instance of parent class
};
Parent:
var FooThing = function(options) {
ThingBase.call(this, options);
};
util.inherits(FooThing, ThingBase);
FooThing.someMethod = function() {
var data = 'some data';
var newFooThing = this.mapper(data); // should return new FooThing instance
};
The reason why I wouldn't just create a new instance from someMethod is that I want mapper to do a bunch of stuff to the data before it returns an instance. The stuff it will need to do is the same for all classes that inherit from Base. I don't want to clutter up my classes with boilerplate to create a new instance of itself.
Is this possible? How might I go about achieving something like this?
Assuming that FooThing.prototype.constructor == FooThing, you could use
ThingBase.prototype.mapper = function(data) {
return new this.constructor(crunch(data));
};
All other solutions would "clutter up [your] classes with boilerplate [code]", yes, however they don't rely on a correctly set constructor property.

Reorganising a lot of methods built on the prototype chain

I've started to write some code to implement a simple game in JavaScript. The basic idea is that dealer.game holds a bunch of objects (player,hand,funds etc) which hold the current state of the game. Then I have various methods which manipulate these objects. I've chosen to use the prototype chain as there could be multiple instances of the dealer.game instance so I wanted shared methods between these instances.
working fiddle:
http://jsfiddle.net/BhPrQ/
and the code:
dealer = {}
dealer.game = function() {
this.player = {};
this.hand = {};
this.set = {};
this.funds = {};
this._drawBoard();
};
dealer.game.prototype._drawBoard = function() {
//draw board in svg here
};
dealer.game.prototype.addPlayer = function(name,funds) {
this.setFunds(name,funds);
this._drawPlayer(name);
};
dealer.game.prototype._drawPlayer = function(name) {
this.player[name] = '';
};
dealer.game.prototype._getPlayer = function(name) {
this.player[name] = '';
};
dealer.game.prototype.setFunds = function(name,funds) {
this.funds[name] = funds;
};
dealer.game.prototype.removeFunds = function() {
};
dealer.game.prototype.drawFunds = function() {
};
var poker = new dealer.game();
poker.addPlayer("jenny",200);
poker.addPlayer("jack",100);
console.log(poker.player);
console.log(poker.funds);
The problem I'm seeing straight away is with even this minimal boilerplate of code adding methods to the object via the prototype chain is going to become messy. I've got a bunch of methods that do stuff to the player and then more that do stuff to the funds...as this grows I can see that I'm going to end up with a huge amount of methods directly linked off the prototype chain which are all mixed in terms of what they do. I know there's technically nothing wrong with this but Is there are better way to organise this? I considered separate objects that require instantiation...something like:
dealer.funds = function() {
};
dealer.funds.prototype.addFunds = function() {
};
But the problem with this is that the instantiated funds object will no longer have access to the core player,hand,set or funds objects contained within player.game.
How do I reorganise this?
The answer was staring me in the face. Create separate classes for the separate parts of my application:
dealer = {};
dealer.game = function() {
this.player = {};
};
dealer.game.prototype.addPlayer = function(name,funds) {
//assign the object returned by dealer.player to my game.player object
//this way my application always has access to all players that have been created
this.player[name] = new dealer.player();
};
dealer.player = function() {
//do some stuff and then return the object
return this;
};

how to have Javascript Object creation pattern with Reusable methods and private properties?

Considering object creation patterns with private properties, one way to do is :
function MyStack (){
var list = [],
index = 0;
this.push = function(val){
return list[index++] = val;
};
this.pop = function(){// ...}
}
var stack1 = new MyStack(); stack1.push(5);
var stack2 = new MyStack(); stack2.push(11);
Problem with this: Every instance of Stack has it's own copy of methods 'push' and 'pop'.
Another way for implementing constructor method is:
function MyStack(){
this.list = [];
this.index = 0;
}
MyStack.prototype = {
insert: function(val){
return this.list[this.index++] = val;
},
pop:function(){//...}
}
Problem here: We lose the privacy of list and index.
Is there a way, such that we can have both methods reuse among instances and privacy of properties ?
I understand that we can have this for methods that don't operate on any state of the object, but I am talking more about those methods that do operate on the state.
Yes. I've edited this code so it's actually fully functional as you had intended it to work. It seems a bit redundant to me, but, it does provide you the ability to provide a public interface, but to keep your variables private and control the way the user interacts with them.
function MyStack(){
var list = [];
var index = 0;
this.getIndex = function(){
return index;
}
this.setIndex = function(val){
index = val;
}
this.list = function(val){
if(val){
// setter if a value was provided. Illustrating how you can control
// index, which I assume is the point of having these things private
// to begin with
return list[this.setIndex(this.getIndex() + 1)] = val;
}
// always return list - acts like a getter
return list;
}
}
MyStack.prototype = {
insert: function(val){
return this.list(val);
},
pop:function(){}
}
var stack1 = new MyStack();
stack1.insert(5);
var stack2 = new MyStack();
stack2.insert(11);
You should check out John Resig's Simple Javascript Inheritance. It is a great read, and it has been extended to provide support for privates, aptly called Privates.js;
A constructor function may return any object (not necesserily this). One could create a constructor function, that returns a proxy object, that contains proxy methods to the "real" methods of the "real" instance object. This may sound complicated, but it is not; here is a code snippet:
var MyClass = function() {
var instanceObj = this;
var proxyObj = {
myPublicMethod: function() {
return instanceObj.myPublicMethod.apply(instanceObj, arguments);
}
}
return proxyObj;
};
MyClass.prototype = {
_myPrivateMethod: function() {
...
},
myPublicMethod: function() {
...
}
};
The nice thing is that the proxy creation can be automated, if we define a convention for naming the protected methods. I created a little library that does exactly this: http://idya.github.com/oolib/
I think in both approaches you mentioned, When ever object is created using constructor pattern the properties will get copied to its objects. This you mentioned for the 1st approach as the concern. I feel the same will be applied for the second approach also along with your concern in this approach.
We generally go to the second approach you mentioned when ever we want to extend the properties of "MyStack" to some other class.
Lets say i want to extend your class MyStack to MyTest like below
var dummy = function();
dummy.prototype = MyStack.prototype;
var MyTest = function(){
};
MyTest.prototype = new dummy(); // Assigning MyStack properties to MyTest
var obj = new MyTest();

Categories