0

As you can see from my code sample, I am wondering why the following thing doesn't work. I have an object with an object as a property (will call it prop in the text below). When I assign the values to the prop in the function, those values are there, because obviously it is passed by reference, but I don't understand why the prop can be referenced to point to another object.

In the case of setting the prop to another object, I just get the empty object, as it is in start. What am I missing here?

const person = {
  basic: {}
}


function initPersonBasics(b) {
  // doesn't work
  b = {
    firstName: 'John',
    lastName: 'Doe'
  }

  // works
  // b.firstName = 'John';
  // b.lastName = 'Doe';
}




initPersonBasics(person.basic);
console.log(person);

2 Answers 2

2

Inside the initPersonBasics() function, the argument b behaves like a local variable. When the function starts, it is already initialized with the value of the first argument of the function (person.basic).

But the statement

b = {
    firstName: 'John',
    lastName: 'Doe'
}

puts a different value in b; it doesn't change person.basic in any way.

As you already noted, if you don't assign a new object to b and set b.firstName and b.lastName instead, the values are stored in person.basic. This happens because JavaScript assignment doesn't copy the objects but stores references to them.

There are several ways to make it work as you want. You have already discovered one of them: store the values one by one in the properties of b (which is an alias of person.basic during the execution of the function call).

Another option is to use Object.assign():

function initPersonBasics(b) {
    Object.assign(b, {
        firstName: 'John',
        lastName: 'Doe'
    });
}

Please note that it doesn't work in older browsers (and even in some newer ones). Carefully check the Browser compatibility section.

Another option (that works in all browsers) is Object.defineProperties() but its syntax is more verbose:

function initPersonBasics(b) {
    Object.defineProperties(b, {
        firstName: {
            value: 'John',
            writable: true,
        },
        lastName: {
            value: 'Doe',
            writable: true,
        }
    });
}

Please note that if you don't mention writable: true for a property, it becomes read-only and cannot be assigned to (and no error is reported).

Sign up to request clarification or add additional context in comments.

Comments

1

const person = {
  basic: {}
}


function initPersonBasics(b) {
  b = {
    firstName: 'John',
    lastName: 'Doe'
  };

  console.log(b);
}

initPersonBasics(person.basic);
console.log(person);

The reason is that you are re-assigning b to point to another object inside initPersonBasics. But that doesn't change where person.basic points to.
What you are doing is similar to this simple code:

function foo(i) {
    i = 42;
}

let j = 10;
foo(j);

You wouldn't expect j to be 42 after the call to foo, would you?

1 Comment

I definitely wouldn't, but I think I understand now. The fact that "basic" object points somewhere means that I can change its values, not where it completely points. Something similar as with pointers in c. Thanks!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.