2

I have a variable whose value is partly defined in terms of another variable. I want to change the value of that variable so that the initial variable also changes. But this doesn’t happen. Look at the second line:

var offset = 0;
var message = "the number is " + offset;

If I modify offset, then message doesn’t change:

console.log(message); // This says "the number is 0".
offset += 20;         // `offset` is changed to `20`.
console.log(message); // The message is still "the number is 0".

message, in this case, would then be called a “reactive” variable.

Why doesn’t it work, and how would I solve it?

Sebastian Simon
  • 18,263
  • 7
  • 55
  • 75
Galivan
  • 4,842
  • 9
  • 44
  • 76
  • That's not how variables work in any language that I'm aware of. – bejado Mar 07 '17 at 00:01
  • it doesn't work because variables in JavaScript (as in most languages) use eager assignment rather than lazy assignment. To achieve what you want, you'd probably need to construct message as a function. – Hamms Mar 07 '17 at 00:01
  • Not *defined*, built. You have a variable whose value is partly *built* with another variable. How to solve it? Build `message` again with the new value. And because it is annoying writing the same code over and over again, put it in a *(template)* function. – Thomas Mar 07 '17 at 00:04
  • The same question for PHP: [PHP: Evaluating variable in string, and then changing value of variable](/q/11221360/4642212). – Sebastian Simon Nov 20 '22 at 06:20

4 Answers4

2

The expression 'the number is' + offset is only evaluated once. It doesn't matter how many times you update offset, JavaScript does not keep track of any relation between message and offset, they are two separate variables.

As was suggested, you could use a function to represent the message instead of a variable.

var offset = 0;

function message() {
    return 'the number is ' + offset;
}

console.log(message());  
offset += 20;             
console.log(message());   

This way, the message gets recomputed each time.

bejado
  • 1,430
  • 12
  • 19
2

Why doesn't it work

When you did 'the number is ' + offset, the value of offset was read then and there to create a new value, the string 'the number is 20', which was assigned to message. The new value doesn't "know" how it was created and therefore cannot recompute itself. That's simply not how JavaScript works.

I want to change the value of that variable so that the initial variable also changes.

That's not possible with variables. But you can use an object with a getter to achieve a similar effect:

var obj = {
  offset: 0,
  get message() {
    return 'the number is ' + this.offset;
  },
};

console.log(obj.message);
obj.offset += 20;
console.log(obj.message);

(Note: the getter is not necessary you could also just create a normal method/function and call it as obj.message())

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
1

It shows up 0 in both cases, because while you are setting it, the offset value is 0 and that's the information which the message variable will hold until you change it's value.

var offset = 0;
var message = 'the number is ' + offset;
console.log(message);  
offset += 20;             
console.log(message);

You have to reassign (refresh) the offset variable to the message variable to make the changes visible.

var offset = 0;
var message = 'the number is ' + offset;
console.log(message);  
offset += 20;  
message = 'the number is ' + offset;
console.log(message);
kind user
  • 40,029
  • 7
  • 67
  • 77
1

Its just a simple assignment that when program flow reach it, concatenates "the number is" to value of offset & continues towards next lines to the end of program.

This is the nature of Javascript, The primitive types (Number, String, etc.) are passed by value. So changes in offset won't be reflected in message.

The variable doesn't "hold" the object, it holds a reference. You can assign that reference to another variable, now both reference the same object. It's always pass by value (even when that value is a reference...). There's no way to alter the value held by a variable passed as a parameter, which would be possible if JS supported passing by reference.From Here

In order to have an always dependent value of message, you can define it as a function:

var offset = 0;
var message = function(){
  return('the number is ' + offset);
}

console.log(message());   //this says 'the number is 0'

offset +=20;             //offset is changed to 20

console.log(message());  //this says 'the number is 20'
Community
  • 1
  • 1
behkod
  • 2,647
  • 2
  • 18
  • 33
  • 2
    *"The primitive types (Number, String, etc.) are passed by value."* Careful with terminology here. "Pass by value" and "pass by reference" usually describe the relationship between **variables** (/parameters) . The actual "type" of the value the variable holds is irrelevant. You might be thinking of *value types* (primitive) and *reference types* (objects), but that has nothing to do with "pass by value". See https://en.wikipedia.org/wiki/Evaluation_strategy .The quote is correct though. – Felix Kling Mar 07 '17 at 07:47
  • Agreed, the answer isn’t quite correct. It’s not about data types. All variables are bound by value. For objects, the value just _is_ the reference. There isn’t an inherent difference between objects and primitives that is relevant to variable bindings. – Sebastian Simon Oct 19 '21 at 02:11