1

I am trying to understand why object destructuring is changing the scope?

(function() {
    var o = {
        add: function(a , b) {
            return a + b;
        },
        log: function () {
            console.log(this);
        }
    }
    var { log } = o;
    o.log();
    log();
})();

this code will log two different objects

the first one is object o as expected but the second will log the global object

UPDATE (3 - May - 2021): If you have the same question and looking for a more detailed answer, read this one as well: How does the "this" keyword work?

Mahmood Sajjadi
  • 412
  • 5
  • 12
  • 2
    This actually has nothing to do with destructuring, but rather with bound (`o.log()`) vs unbound (`log()`) calls. You'll get the right `this` only with the former. – georg Apr 28 '21 at 22:50
  • this is a good fundamental question for interviews – King Friday Apr 28 '21 at 23:18

3 Answers3

3

It's not exactly right

function log() {
  console.log('na aahh')
}
(function() {
    var o = {
        add: function(a , b) {
            return a + b;
        },
        log: function () {
            console.log('hi, i am locally scoped');
        }
    }
    var { log } = o;
    o.log();
    log();
})();

Run and see.

But...when you log this it always takes on the nearest scope which happens to be global because its detached from the o when destructured.

Try doing something like this...

function log() {
  console.log('nananana')
}
(function() {
    var o = {
        add: function(a , b) {
            return a + b;
        },
        log: function () {
            console.log(this);
        }
    }
    o.log = o.log.bind(o);
    var { log } = o;
    o.log();
    log();
})();

and notice how it retains this on destructure.

Also... side note, you should use let over using var as let when declared also has block scope which is pretty nice.

Happy coding sir.

King Friday
  • 19,950
  • 9
  • 78
  • 78
2

What you are doing is more or less equivalent of

const log = o.log

You have extracted a method from an object, but trying to call it without doing anything else, this will not refer to the original object. You need to bind it.

const log = o.log.bind(o)
Federkun
  • 30,933
  • 8
  • 62
  • 80
0

It depends on what you set this to be:

(function() {
var o = {
    add: function(a , b) {
        return a + b;
    },
    log: function () {
        console.log(this);
    }
}
var { log } = o;
o.log();
// equivalent to
log.call(o);
})();