0

Here is a dummy example:

const obj = {foo: '123'};

function logObj(obj) {
    setInterval(function() {
        console.log(obj);
    }, 100)
}

function overWrite(obj) {
    setTimeout(function(){
        console.log('overwriting')
        obj = {foo: 'bar'}
    }, 1000);
}

logObj(obj)
overWrite(obj)

I'm expecting to see { foo: '123' } every 100ms until overwriting is called and then to see { foo: 'bar' }. However the object is never over-written and I always see 123.

EDIT

I do not want to change just one of the keys; I do in fact want to replace the entire object, so doing obj.foo = 'bar' is not a solution

Kousha
  • 32,871
  • 51
  • 172
  • 296
  • 1
    As I said in my comments, then do not pass the obj into the methods. Just reference the global variable – Taplar Mar 22 '19 at 18:00
  • 2
    Change `const` to `let` and change `function overWrite(obj)` to `function overWrite()` so that overWrite can modify `obj` in the outer scope. – Paul Mar 22 '19 at 18:01
  • @Paulpro That wouldn't work, since `logObj` works with a copy of the `{ foo: '123' }` reference provided by the `logObj(obj)` call. You have to remove both function parameters, so `console.log(obj)` doesn't work with a copy and `obj = { foo: 'bar' }` sets the global variable. – 3limin4t0r Mar 22 '19 at 20:14

3 Answers3

2

Instead of obj = {foo: 'bar'} do obj.foo= 'bar'

const obj = {
  foo: '123'
};

function logObj(obj) {
  setInterval(function() {
    console.log(obj);
  }, 100)
}

function overWrite(obj) {
  setTimeout(function() {
    console.log('overwriting')
    obj.foo = 'bar'
  }, 1000);
}

logObj(obj)
overWrite(obj)
brk
  • 48,835
  • 10
  • 56
  • 78
2

To get a better understanding of what's happening let's rename the variables.

const a = { foo: '123' };

function logObj(b) {
  setInterval(function () {
    console.log(b);
  }, 1000);
}

function overWrite(c) {
  setTimeout(function () {
    console.log('overwriting');
    c = { foo: 'bar' };
  }, 5000);
}

logObj(a);
overWrite(a);

Variables passed to a function are copies of the primary value.

First you call logObj with a copy of the value of a (a reference to object { foo: '123' }). This reference will be available as b in the function.

Then you call overWrite with a copy of the value of a (a reference to object { foo: '123' }). This reference will be available as c in the function. In the callback you replace the contents of c with a new reference. However this does not effect the contents of a or b and is only available during the function body.

Here is an simplified example:

variable diagram

3limin4t0r
  • 19,353
  • 2
  • 31
  • 52
-1

The solution is simple, change your const obj to var obj = {...}.

As you can see in this article there's a difference when declaring variables with var, const or let.

const cannot be updated or re-declared

Kodiak
  • 492
  • 6
  • 13
  • 1
    The issue doesn't have to do with using constants in this case, however that is a good general rule to follow. – Steven Stark Mar 22 '19 at 19:57
  • The user expects a different (= changed or updated) object after the timeout runs out. Therefore I clearly think that this is the issue here. – Kodiak Mar 22 '19 at 20:00
  • that is not the case, no. This is about references and not about the scope. – Steven Stark Mar 22 '19 at 20:04