Reputation: 47
I'm trying to create a global object with a series of 'slave' properties that are derived from the value of one 'master' property in the same object - something like:
var x = 5;
var myObj = {
master : 17,
slave1 : this.master + x,
slave2 : (this.master / 2.2) + 1,
slave3 : Math.floor(this.slave2)
//etc.
};
I realize this is horribly wrong as is, but the concept is there. What I'd like to do is have all these 'slave' properties updated as myObj.master
is updated. What's the cleanest way to do this? Does each slave value need to be explicitly set by some event handler that fires when myObj.master
is changed...?
Upvotes: 0
Views: 762
Reputation: 26730
If you are not targeting Internet Explorer users, try using getters and setters.
var x = 5;
function myObj()
{
this.master = 17;
this.getSlave1 = function() {return this.master + x;},
this.getSlave2 = function() {return (this.master / 2.2) + 1;},
this.getSlave3 = function() {return Math.floor(this.getSlave2());}
}
myObj.prototype = {
get slave1() {
return this.getSlave1();
},
get slave2() {
return this.getSlave2();
},
get slave3() {
return this.getSlave3();
}
};
In action:
window.onload = function()
{
o = new myObj();
document.write("Master: "+o.master+"</br>");
document.write("Slave 1: "+o.slave1+"</br>");
document.write("Slave 2: "+o.slave2+"</br>");
document.write("Slave 3: "+o.slave3+"</br></br>");
o.master = 42;
document.write("Master: "+o.master+"</br>");
document.write("Slave 1: "+o.slave1+"</br>");
document.write("Slave 2: "+o.slave2+"</br>");
document.write("Slave 3: "+o.slave3+"</br>");
}
produces the output:
Master: 17
Slave 1: 22
Slave 2: 8.727272727272727
Slave 3: 8
Master: 42
Slave 1: 47
Slave 2: 20.09090909090909
Slave 3: 20
This code will never work in any version of Internet Explorer, past, present or future. However, it the slave values can still be accessed using the getSlaveX()
functions.
Upvotes: 4
Reputation: 25463
You could simulate getters using valueOf
and toString
, but it's a little unwieldy.
function makeValueOf(fn) {
return {
valueOf: fn,
toString: fn
};
}
function makeObj(master, x) {
var self = {};
self.master = master;
self.slave1 = makeValueOf(function () { return self.master + x; });
self.slave2 = makeValueOf(function () { return self.master / 2.2 + 1; });
self.slave3 = makeValueOf(function () { return Math.floor(self.slave2); });
return self;
}
var myObj = makeObj(6, 2);
alert(myObj.slave1 + 5); // 13
Upvotes: 0
Reputation: 776
You don't want to expose the slaves and allow them to be set since that would erase their link to master. So they should be private.
var x = 5;
var MyObject = function() {
var master = 17;
this.setMaster = function(newMaster) {
master = newMaster;
};
this.getMaster = function() {
return master;
};
var slaves = {
slave1 : function() { return master + x },
slave2 : function() { return (master / 2.2) + 1 },
slave3 : function() { return Math.floor(this.slave2()) }
};
this.getSlave = function(slave) {
return slaves[slave]();
};
};
var o = new MyObject();
o.getSlave("slave1"); // 22
o.getSlave("slave3"); // 8
o.setMaster(3);
o.getSlave("slave1"); // 8
o.getSlave("slave3"); // 2
Upvotes: 0
Reputation: 827694
Another option can be to use a constructor function to build your object, e.g:
var x = 5;
function MyObj(master) {
this.master = master;
this.slave1 = this.master + x,
this.slave2 = (this.master / 2.2) + 1,
this.slave3 = Math.floor(this.slave2)
}
var myObj = new MyObj(17);
In the above example I use a master
argument and a reference to the x
global property, if you don't have x
available in that scope, you could provide also an argument for it.
You can also build your object in several steps:
var myObj = {
master : 17
}, x = 5;
myObj.slave1 = myObj.master + x;
myObj.slave2 = (myObj.master / 2.2) + 1;
myObj.slave3 = Math.floor(myObj.slave2);
Upvotes: 1
Reputation: 65156
David's answer is one option, but if you want to cache the results instead of recalculating them every time, do it the other way round:
var x = 5;
var myObj = {
setMaster: function(val) {
this.master = val;
this.slave1 = this.master + x;
// ...
}
};
myObj.setMaster(17);
Upvotes: 2
Reputation: 943981
You would probably be best off using functions.
var x = 5;
var myObj = {
master : 17,
slave1 : function() { return this.master + x },
slave2 : function() { return (this.master / 2.2) + 1 },
slave3 : function() { return Math.floor(this.slave2()); }
//etc.
};
var example = myObj.slave3();
Upvotes: 2