The title is probably worded horribly, but I'm not sure how to articulate what I'm trying to do here.
Essentially what I have is a class that contains two methods:
objFactory
that returns an object that contains three properties (value1,value2,value3) and another function bound to the object. I.e. myObj = {value1: 1, value2: 2, value2: 3, func()}
changeValueProperties
that will create values 1-3 based on an input value for myObj
.The user calls the factory method and an object is returned. The intent is that the user doesn't modify values 1-3 directly in the returned object, rather they call the built in method that computes those values and updates them on the object for the user. i.e. changeValueProperties
is suppose to be a blackbox to the end user, they don't know how to calculate value1, value2, value3 for themselves.
The main issue here being the 'this' keyword. 'this' is referring to the MyTestClass, when I really want it bound to the returned object, so that its internal properties can be modified. I imagine something like this can be achieved via the call/apply/bind methods, but I'm not quite clear how to achieve that in this particular context. Especially when the updateValues
method will use one of the class's own methods to do the computation.
I'm also open to alternative suggestions in terms of architecture. I realize this probably isn't kosher and there is probably a better method to implement the strategy I'm going for.
class MyTestClass {
dummyData;
constructor() {
this.dummyData = 100;
}
changeValueProperties(value) {
return {
value1: value*1,
value2: value*2,
value3: value*3
}
}
objFactory(value, ..other parameters) {
let computedValues = this.changeValueProperties(value);
let updateValues = (newValue) => {
let computedValues = this.changeValueProperties(newValue);
// This is where updateValues needs to update
// values 1-3 in myReturnedObj that has been returned to the calling user.
// this keyword can't be used, because it is bound to MyTestClass and not
// myReturnObj
this.value1 = computedValues.value1;
this.value2 = computedValues.value2;
this.value3 = computedValues.value3;
}
let myReturnObj = {
value1: computedValues.value1,
value2: computedValues.value2,
value3: computedValues.value3,
updateValues: updateValues
}
return myReturnObj
}
}
const myClass = new MyTestClass();
let myObj = myClass.objFactory(10,...other parameters for object generation);
// {value1: 10, value2: 20, value3: 30, ...}
myObj.updateValues(20);
// should return {value1: 20, value2: 40, value3: 60, ...}
It seems that you want this
in updateValues
to refer to two different objects. You have to decide on one of them, or neither.
To use neither, refer to the objects through variables:
objFactory(value) {
const computedValues = this.changeValueProperties(value);
const myTest = this;
const myReturnObj = {
...computedValues,
updateValues(newValue) {
const newComputedValues = myTest.changeValueProperties(newValue);
// ^^^^^^
Object.assign(myReturnObj, newComputedValues);
// ^^^^^^^^^^^
};
return myReturnObj;
}
This uses the old var self = this
pattern [1][2][3].
Now you can either
make updateValues
a method that uses this
to refer to the myReturnObj
:
objFactory(value) {
const computedValues = this.changeValueProperties(value);
const myTest = this;
return {
...computedValues,
updateValues(newValue) {
const newComputedValues = myTest.changeValueProperties(newValue);
Object.assign(this, newComputedValues);
// ^^^^
};
}
or make updateValue
an arrow function so that it uses this
from its parent scope:
objFactory(value) {
const computedValues = this.changeValueProperties(value);
const myReturnObj = {
...computedValues,
updateValues: (newValue) => {
const newComputedValues = this.changeValueProperties(newValue);
// ^^^^
Object.assign(myReturnObj, newComputedValues);
};
return myReturnObj;
}