Reputation: 117
I mean the question in the title in the mathematical sense. Given a variables x and y, these can be related by an equation y=f(x), where f is some mathematical function. This means when x=2, y=f(2), when x=-5, y=f(-5), and so on. This is such a natural thing in a mathematical context I would hope there is a simple means of achieving this behavior in javascript. For concreteness lets imagine the function f(x)=2x. We can implement this in code by
function f(x){
return 2*x
}
but the following behavior is the default
x=3
y=f(x)
y // returns 6
x=4
y // still returns 6
Even though we originally wrote y=f(x) this relation doesn't persist as x changes.
I suppose a simpler version of this problem is when f is just the identity function and we use y=x. You could write y=x, change x, and y would still be the old value of x depending on if x held a primitive or reference value and how we changed the value of x.
It seems that in order to copy a value so a relation y=x persists we have to (1) copy it by reference and (2) change values such as by point.xCoord = 6 so as to not mess up the reference information. I wonder if there is a solution like this that works for y=f(x) generally instead of just y=x.
The workaround I'm using now is storing x in an object that also keeps track of values which depend on it, and only updating x by calling methods which also update each of the values which depend on x. This feels like an ugly solution, so I'm wondering if there is a better way.
Upvotes: 1
Views: 1117
Reputation: 18609
JavaScript !== Math
.Period.
JavaScript is a bit crazy flexible language, so technically there is a way to do it.
But come on -- JS isn't math. If any of your fellow developers looks at the crazy workaroud you came up with, they'll mind twice before working with you again.
So, what to do?
As mentioned in the comments, simply store a function in y
.
const f = x => 2*x //This is an alternative declaration of `f`, that does the same
// vv--- no arguments, this will use the x from the outside.
const y = () => f(x)
//^^^--- const, because we won't expect y itself to change, but rather just the value returned by it
let x = 3
// call it ---vv
console.log(x, y()) //y() === 6, fine!
x = 2
console.log(x, y()) //y() === 4!
The reason why you couldn't use this to define other functions simply doesn't exist!
//...
// vv--- call it, as always
const z = () => y() + 1
console.log(x, y(), z()) //z() === 5!
Try it:
const f = x => 2*x //This is an alternative declaration of `f`, that does the same
// vv--- no arguments, this will use the x from the outside.
const y = () => f(x)
//^^^--- const, because we won't expect y itself to change, but rather just the value returned by it
let x = 3
// call it ---vv
console.log('x =', x, 'y =', y()) //y() === 6, fine!
x = 2
console.log('x =', x, 'y =', y()) //y() === 4!
// vv--- call it, as always
const z = () => y() + 1
console.log('x =', x, 'y =', y(), 'z =', z()) //z() === 5!
x = 42
console.log('x =', x, 'y =', y(), 'z =', z()) //x = 42, y = 84, z = 85
Upvotes: 0
Reputation: 2810
UPDATE: would this answer help you in your situation?
Sample:
function Model() {
this.varX = ko.observable(1);
this.varY = ko.computed(function() {
return this.varX();
}, this);
}
var model = new Model();
setInterval(function() {
model.varX(model.varX() + 1);
console.log("x is updated ", model.varX());
console.log("y value ", model.varY());
}, 1000);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
Upvotes: 2
Reputation: 101730
What you're asking about is simply not how JavaScript variables work. In the long run, I think you would probably benefit from looking into functional programming concepts and the use of immutable variables.
However, it is possible to create something similar to what you describe by encapsulating the function in an object method, specifically the valueOf
and toString
methods, which have special meanings in JavaScript.
For example:
const track = (f) => ({ valueOf: f , toString: () => f().toString() });
let x = 7;
let y = 8;
const z = track(() => x * x + 2 * y);
// further derive a value using z
const a = track(() => z - x);
console.log(`*** x = ${x}, y = ${y} ***`);
console.log('z =', z.valueOf());
// valueOf() is implicitly evaluated if the variable is used
// in a mathematical expression
console.log('z * 2 =', z * 2);
console.log('a =', a * 1);
// coerce to a string value
console.log(`z = ${z}, a = ${a}`);
// change x
x = 5;
console.log(`*** x = ${x}, y = ${y} ***`);
console.log('z * 2 =', z * 2);
console.log('a =', a * 1);
// change y
y = 50;
console.log(`*** x = ${x}, y = ${y} ***`);
console.log('z * 2 =', z * 2);
console.log('a =', a * 1);
// compare using valueOf()
const equals = (l, r) => l.valueOf() === r.valueOf();
console.log('equals(a, 120)', equals(a, 120));
console.log('equals(a, 125)', equals(a, 125));
Upvotes: 3
Reputation: 812
I am unable to find errors in your code but, I'll try to rewrite it
function f(x) {
return (x*2);
}
var x = 2;
var y = f(x);
console.log(y);
x = 3;
y = f(x);
console.log(y);
//If you want to store the output then, y = f(2); or y = f(3)
Try running the above snippet. It works for me.
Upvotes: -1