I want to create a dependent property on my javascript object.
I have an object like in the code snippet. I want to update isPawn property; when isNew property changes.
Is there a way for do something similar that automatically;
if(isNew){
isPawn = true;
}
But they are not have to be same. isNew can be 'false', when isPawn is 'true'
My Object:
var Soldier = function (id,name) {
this.id = id;
this.name = name;
this.isPawn = false;
this.isNew = false;
}
Yes, you can do this using a setter, here is an example:
class Soldier {
#isNew = false;
constructor(id,name) {
this.id = id;
this.name = name;
this.isPawn = false;
}
set isNew(val) {
this.#isNew = val;
this.isPawn = val;
}
get isNew() {
return this.#isNew;
}
}
const soldier = new Soldier();
soldier.isNew = true;
console.log('isNew:', soldier.isNew, 'isPawn', soldier.isPawn);
soldier.isNew = false;
console.log('isNew:', soldier.isNew, 'isPawn', soldier.isPawn);
soldier.isPawn = true;
console.log('isNew:', soldier.isNew, 'isPawn', soldier.isPawn);
#isNew is a private field in this case I'm using it to keep track of what the value of isNew should be (what the getter should return).
Here is an example using a function instead of a class:
var Soldier = function(id, name) {
this.id = id;
this.name = name;
this.isPawn = false;
this.isNewPriv = false;
Object.defineProperty(this, 'isNew', {
set: function(val) {
this.isNewPriv = val;
this.isPawn = val;
},
get: function() {
return this.isNewPriv
}
});
}
var soldier = new Soldier(1, 'none');
soldier.isNew = true;
console.log("isNew:", soldier.isNew, "isPawn:", soldier.isPawn);
soldier.isNew = false;
console.log("isNew:", soldier.isNew, "isPawn:", soldier.isPawn);
soldier.isPawn = true;
console.log("isNew:", soldier.isNew, "isPawn:", soldier.isPawn);
Make a class and instantiate as needed
class Soldier {
constructor(id, name, isNew) {
this.id = id;
this.name = name;
this.isPawn = isNew? true : {something : "whaterverElse"};
this.isNew = isNew;
}
DoSomething(){
this.isNew = false;
}
}
var soldier = new Soldier(1, 'Tim', true);
console.log(soldier);
function somethingElseHappened(){
soldier.DoSomething();
}
somethingElseHappened();
console.log(soldier);
you can make a default values for this properties like this:
var Soldier = function (id,name,isPawn = false,isNew = false) {
this.id = id;
this.name = name;
this.isPawn = isPawn;
this.isNew = isNew;
}
and if you want to change there values to any object for you just do like this:
var newSolider = new Solider(1,"foo",false,true);
Related
I have two classes, the environment class has a property of stations which supposed to have multiple instances of the station class. I'm trying to add an increase method in the station that will increase the value of the station and will decrease the pending value of the parent environment by the same amount. I've tried to mess around with super, parent and Object.getPrototypeOf, but as I'm new to JavaScript OOP (and to JavaScript by itself) I'm struggling. Any help!
class enviroment {
constructor(name) {
this.name = name;
this.pending = 0;
this.stations = [];
}
newStation(value = 0, name = null) {
this.stations.push(new station(value, name));
return this;
}
}
class station {
constructor(value = 0, label = null) {
this.value = value;
this.label = label;
this.isTaken = false;
}
increase(increasment) {
this.value += increasment;
this.parent.pending -= increasment; // <---- HERE
return this;
}
}
You could try it by adding a reference for the environment to the stations like:
class enviroment {
constructor(name) {
this.name = name;
this.pending = 0;
this.stations = [];
}
newStation(value = 0, name = null) {
this.stations.push(new station(value, name, this));
return this;
}
}
class station {
constructor(value = 0, label = null, environment = null) {
this.value = value;
this.label = label;
this.isTaken = false;
this.environment = environment;
}
increase(increasment) {
this.value += increasment;
if(this.environment)
this.environment.pending -= increasment; // <---- HERE
return this;
}
}
I have some javascript code which looks like this - it's very repetitive, and as you can see follows a very defined pattern:
var AttachmentBuilder = function(){
this.attachment = {};
}
AttachmentBuilder.prototype.text = function(value){
this.attachment.text = value;
return this;
}
AttachmentBuilder.prototype.fallback = function(value){
this.attachment.fallback = value;
return this;
}
AttachmentBuilder.prototype.color = function(value){
this.attachment.color = value;
return this;
}
I had the idea to refactor this like:
var AttachmentBuilder = function(){
this.attachment = {};
}
passThrough(AttachmentBuilder.prototype,"attachment","text");
passThrough(AttachmentBuilder.prototype,"attachment","fallback");
passThrough(AttachmentBuilder.prototype,"attachment","color");
function passThrough(obj, apply, name){
obj[name] = function(param){
this[apply][name] = param;
}
return this;
}
But the context of this is not correct, and it does not behave like the long-hand version.
Below is a working example demoing the working and not working versions.
var AttachmentBuilder_Original = function(){
this.attachment = {};
}
AttachmentBuilder_Original.prototype.text = function(value){
this.attachment.text = value;
return this;
}
AttachmentBuilder_Original.prototype.fallback = function(value){
this.attachment.fallback = value;
return this;
}
AttachmentBuilder_Original.prototype.color = function(value){
this.attachment.color = value;
return this;
}
var original = new AttachmentBuilder_Original();
original.text("Text").color("Red").fallback("Fallback");
console.log("original",original.attachment);
/* ------------------------------------- */
var AttachmentBuilder_New = function(){
this.attachment = {};
}
passThrough(AttachmentBuilder_New.prototype,"attachment","text");
passThrough(AttachmentBuilder_New.prototype,"attachment","fallback");
passThrough(AttachmentBuilder_New.prototype,"attachment","color");
function passThrough(obj, apply, name){
obj[name] = function(param){
this[apply][name] = param;
}
return this;
}
var adjusted = new AttachmentBuilder_New();
adjusted.text("Text").color("Red").fallback("Fallback");
console.log("adjusted",adjusted.attachment);
I'm also interested if there is a more ES6-like way of solving this same issue of repetition.
Your higher order function looks good. Probably simple mistake of putting return statement in the wrong place.
function passThrough(obj, apply, name){
obj[name] = function(param){
this[apply][name] = param;
return this;
} //^^^^^^^^^^^^
}
Your solution should work, if you do this modification.
var AttachmentBuilder = function(){
this.attachment = {};
}
passThrough(AttachmentBuilder.prototype,"attachment","text");
passThrough(AttachmentBuilder.prototype,"attachment","fallback");
passThrough(AttachmentBuilder.prototype,"attachment","color");
function passThrough(obj, apply, name){
obj[name] = function(param){
this[apply][name] = param;
return this;//<---move return this here
}
//return this;
}
If I have this code
var node = function(n) {
var name = n;
var children = [];
var finished = false;
var failed = false;
this.getName = function() {
return name
};
this.downloadData = function(obj) {
};
this.getChildren = function() {
return children;
};
this.setChildren = function(c) {
Array.prototype.push.apply(children, c);
};
this.isFinished = function() {
return finished;
};
this.setFinished = function() {
finished = true;
}
this.isFailed = function() {
return failed;
}
this.setFailed = function() {
failed = true;
}
};
How can I convert this into an object like:
var a = new node("a");
var j = JSON.stringify(a);
result
{"name":"a","children":[],"finished":false,"failed":false}
thanks
This could be done by implementing the toJSON function.
If an object being stringified has a property named toJSON whose value
is a function, then the toJSON() method customizes JSON
stringification behavior: instead of the object being serialized, the
value returned by the toJSON() method when called will be serialized.
- Mozilla
eg:
var node = function(n) {
var name = n;
var children = [];
var finished = false;
var failed = false;
this.toJson = function toJson() {
return {"name":name ... };
}
}
You need object properties instead of variables.
So, instead of declaring var name = n;, you would declare this.name = n;. Which would make it look something like
var node = function(n) {
this.name = n;
this.children = [];
this.finished = false;
this.failed = false;
///other functions here
}
In something like the following example, how would I go about looping over every object from the apple prototype?
function apple(id,name,color) {
this.id = id;
this.name = name;
this.color = color;
}
apple1 = new apple(0,"Golden Delicious","Yellow");
myapple = new apple(1,"Mcintosh","Mixed");
anotherapple = new apple(2,"Bramley","Green");
/*
for each instance of apple {
if (this one is "Green") { do something }
}
*/
I'd use something like static property that contains references to all instances. You'll add every instance there in the constructor:
function apple(id,name,color) {
this.id = id;
this.name = name;
this.color = color;
apple.instances.push(this);
}
apple.instances = [];
Then, you can loop through apple.instances.
I am using capitalized name for constructor so the syntax highlighter gets it:
function Apple(name,color) {
this.name = name;
this.color = color;
this.id = this.constructor.getId();
this.constructor.instances[this.id] = this;
}
Apple.instances = {};
Apple.getId = (function(){
var i = 0;
return function(){
return i++;
};
})();
/* ... */
var instance, key;
for( key in Apple.instances ) {
instance = Apple.instances[key];
if( instance.color == "green" ) {
delete Apple.instances[instance.id];
}
}
How can I get the YUI3 sendRequest applied to a Datasource to return predefined objects, instead of plain ones?
For example, I have this Base class with its methods:
function Student(id, name){
this.id = id;
this.name = name;
}
Context.prototype.setId = function(id){ this.id = id; };
Context.prototype.setName = function(name){ this.name = name; };
Context.prototype.getId = function(){ return this.id; };
Context.prototype.getName = function(){ return this.name; };
And I have this code that retrieves data from an API, normalizes it and returns data as objects:
var studApiDataSource = new Y.DataSource.Get({source: API_URL});
studApiDataSource.plug(Y.Plugin.DataSourceJSONSchema, {
schema: {
resultListLocator: "response.student",
resultFields: ["id","name"]
}
});
var myCallback = function(e) {
Y.Array.each(e.response.results, function(stud){
Y.log(stud.id+' '+stud.name);
}
}
studApiDataSource.sendRequest({
request: "?cmd=getStudents",
callback: {
success: myCallback,
failure: function (e) { }
}
});
The array of objects retrieved by studApiDataSource.sendRequest() and passed to myCallback are normal objects, with id and name properties. However, I want these to be Student objects, with their member functions too (getId, getName etc)
I'm not sure I fully understand, but you could do something like the following.
var studentJSON = "{\"id\": 17, \"name\":\"my name is\"}";
function Student(obj){
this.name = obj.name;
this.id = obj.id;
}
Student.prototype.setId = function(id){ this.id = id; };
Student.prototype.setName = function(name){ this.name = name; };
Student.prototype.getId = function(){ return this.id; };
Student.prototype.getName = function(){ return this.name; };
YUI().use('json-parse', 'json-stringify', function (Y) {
try {
var stud = new Student(Y.JSON.parse(studentJSON));
alert(stud.getId());
}
catch (e) {
alert(e);
}
});