Access and change properties of parent object in JS - javascript

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;
}
}

Related

How to declare a private member in js classes and extend it to other classes?

Good Evening.
I want to create a parent class vehicle with a private member #manufacturer. I want to extend class vehicle to class car and motorcycle. I declared a const d = new car. If i try to acces to manufacturer by console.log(d.manufacturer) i recive and undefined.
// task 1
class vehicle {
#manufacturer;
name;
constructor(manufacturer, name) {
this.#manufacturer = manufacturer;
this.name = name;
}
get name() {
return this.name;
}
}
class car extends vehicle {
#type;
constructor(manufacturer, name, type) {
super(manufacturer, name);
this.#type = type;
}
get type() {
return this.#type;
}
set type(value) {
if (value.length > 3) this.#type = value;
}
}
class motorcycle extends vehicle {
motortype;
constructor(manufacturer, name, motortype) {
super(manufacturer, name);
this.motortype = motortype;
}
get motortype() {
return this.motortype;
}
set motortype(value) {
if (value.length > 3) {
this.motortype = value;
}
}
}
const e = new motorcycle('audi', 'a3', 'sport');
console.log(e.motortype);
e.motortype = 'supersport';
console.log(e.motortype);
const d = new car('bmw', 'm2', 'cool');
console.log(d.type);
d.type = 'lazy';
console.log(d.type);
console.log(e.name);
console.log(e.motortype);
console.log(d.manufacturer)
I tried to change the constructor in order to fix this problem by putting as well an #manufacturer in the constructor. But i recive an error.
Private properties aren't inherited thus with a car object (subclass) you can't access a private member defined in vehicle (superclass). But you can make the private member accessibile with a public get method like this:
class vehicle {
#manufacturer;
name;
constructor(manufacturer, name) {
this.#manufacturer = manufacturer;
this.name = name;
}
get name() {
return this.name;
}
get manufacturer(){
return this.#manufacturer;
}
}
class car extends vehicle {
#type;
constructor(manufacturer, name, type) {
super(manufacturer, name);
this.#type = type;
}
get type() {
return this.#type;
}
set type(value) {
if (value.length > 3) this.#type = value;
}
}
class motorcycle extends vehicle {
motortype;
constructor(manufacturer, name, motortype) {
super(manufacturer, name);
this.motortype = motortype;
}
get motortype() {
return this.motortype;
}
set motortype(value) {
if (value.length > 3) {
this.motortype = value;
}
}
}
const e = new motorcycle('audi', 'a3', 'sport');
console.log(e.motortype);
e.motortype = 'supersport';
console.log(e.motortype);
const d = new car('bmw', 'm2', 'cool');
console.log(d.type);
d.type = 'lazy';
console.log(d.type);
console.log(e.name);
console.log(e.motortype);
console.log(d.manufacturer)

Update another property, when a property changes?

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);

How to expose only a function and not the variables from a class function?

Suppose I have this code:
function GraphFactory() {
this.nodeNames = [];
this.pinnedNodes = [];
this.initPinnedNodes = function(nodes) {
if (nodes) {
this.pinnedNodes = nodes;
} else {
this.pinnedNodes = [];
}
}
this.checkIfPinned = function(node) {
if (this.pinnedNodes.indexOf(node) > -1) {
return true;
} else {
return false;
}
}
this.addToPinnedNodes = function(name) {
this.pinnedNodes.push(name);
return true;
}
this.removeFromPinnedNodes = function(name) {
this.pinnedNodes.splice(this.pinnedNodes.indexOf(name), 1);
return true;
}
}
let graphFactory = new GraphFactory();
Right now i can access both the function
graphFactory.checkIfPinned(label);
but also directly the variable
graphFactory.pinnedNodes
How would I set things up so only the functions, but not the variables could get accessed?
Use variables instead of properties on the object.
let nodeNames = [];
They'll be closed over by your dynamically assigned instance methods.
Or see this question for the modern approach.
With the current construct, you can use a closure per object, practically a local variable in your constructor function:
function GraphFactory() {
var nodeNames = [];
var pinnedNodes = [];
this.initPinnedNodes = function(nodes) {
if (nodes) {
pinnedNodes = nodes;
} else {
pinnedNodes = [];
}
}
this.checkIfPinned = function(node) {
if (pinnedNodes.indexOf(node) > -1) {
return true;
} else {
return false;
}
}
this.addToPinnedNodes = function(name) {
pinnedNodes.push(name);
return true;
}
this.removeFromPinnedNodes = function(name) {
pinnedNodes.splice(this.pinnedNodes.indexOf(name), 1);
return true;
}
}
let graphFactory = new GraphFactory();
However such variables will not be accessible to methods you add later, from outside. For example that nodeNames exists in vain this way.

Manage JS inheritance failure

I am new to Object Orientated Programming, please have in mind. I have understood how the first part shown here works (it does):
function Car() {
var __registration;
var setReg = function(val) {
__registration= val;
}
var getReg= function() {
return __registration;
}
return {
setReg: setReg ,
getReg: getReg
}
}
var myCar = new Car();
myCar.setReg("LSKM5215");
alert(myCar.getReg() ); //ALERTS LSKM5215
But when trying to manage inheritance on this way of Object Orientated Programming, it just fails once and again:
function Extras(){
var __sound;
var setSound= function(val) {
__sound= val;
}
var getSound= function() {
return __sound;
}
return {
setSound: setSound,
getSound: getSound
}
}
Extras.prototype = new Car();
myCar.setSound("SUPERB SOUNDSYSTEM 2.2"); //TypeError: myCar.setSound is not a function
How could I create inheritance on this case? To make Car() get the private variables about the "soundsystem extras"?
Very grateful.
You not need return when plan use function as constructor.
in derived class you should call base constructor with needed parameters.
in derived class assign proptotype based on base prototype.
Something like this:
function Car() {
var __registration;
this.setReg = function(val) {
__registration = val;
}
this.getReg = function() {
return __registration;
}
}
function Extras() {
Car.call(this);
var __sound;
this.setSound = function(val) {
__sound = val;
}
this.getSound = function() {
return __sound;
}
}
Extras.prototype = Object.create(Car.prototype);
myExtras = new Extras();
myExtras.setReg("LSKM5215");
myExtras.setSound("SUPERB SOUNDSYSTEM 2.2");
document.write("<div>Extras: reg - ", myExtras.getReg(), '</div>');
document.write("<div>Extras: sound - ", myExtras.getSound(), '</div>');
And for ES2015 you can use classes
class Polygon {
constructor(height, width) {
this.height = height;
this.width = width;
}
get area() {
return this.calcArea();
}
calcArea() {
return this.height * this.width;
}
}
class Car {
constructor() {
this.__registration = undefined;
}
set Reg(val) {
this.__registration = val;
}
get Reg() {
return this.__registration;
}
}
class Extras extends Car {
constructor() {
super();
this.__sound = undefined;
}
set Sound(val) {
this.__sound = val;
}
get Sound() {
return this.__sound;
}
}
myExtras = new Extras();
myExtras.Reg = ("LSKM5215");
myExtras.Sound = ("SUPERB SOUNDSYSTEM 2.2");
document.write("<div>Extras: reg - ", myExtras.Reg, '</div>');
document.write("<div>Extras: sound - ", myExtras.Sound, '</div>');

In Javascript, how do I loop through objects inherited from a given constructor?

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];
}
}

Categories