Search code examples
javascriptscopethisdestructuring

Why does destructuring an argument object affect it's 'this' value?


Can someone please tell me why destructuring would affect an object's this value. There are many easy work-arounds to this, but I just want to know what is actually going on here. It seems like it should work, but there is something bizarre happening with the this scope caused by the destructuring. Anyone know?

Here is a simple object:

const user = {
  name: 'John',
  age: 30,
  sayHi() {
    console.log(this); // undefined for foo(), but defined for bar()
    return `hello, ${this.name}`;
  }
};

In foo I use destructuring to access the object keys, but the this value is undefined inside of sayHi().

const foo = ({ sayHi, name }) => {
  console.log(sayHi()); // hello, [empty string]
  console.log('OUTPUT: foo ->  name', name); // John
};

foo(user);

But here, just passing the object in without destructuring, works as expected and the this value is defined.

const bar = person => {
  console.log(person.sayHi()); // hello, John
};

bar(user);

Solution

  • In the first case, by destructuring you've created a separate reference to the sayHi function. When you then call it from the body of foo, this becomes the context for this in the body of sayHi.

    In the second case, you are calling it as person.sayHi, so the context in this case is the containing object - i.e. person. Within sayHi, this is person, and name is defined.

    There's nothing magical about destructuring, if you manually create a reference to the function you'll get the same effect:

    const bar = person => {
      const sayHi = person.sayHi;
      console.log(sayHi()); 
    };