-3

My Sample Code:

var sound = 'woof' //global variable
let dog = {
  //sound: 'woof'
  talk: function() {
    console.log(this.sound)
  }
}

let talkFunction = dog.talk
talkFunction() // result is undefined

I dont understand, when we have a global variable, this reffers to global object, why then sound variable is not called.

Phil
  • 157,677
  • 23
  • 242
  • 245
  • 1
    When you create a function, it has its own scope. So `.talk` has its own context where `sound` is not defined. You can make `talk` as an arrow function, or directly use `sound`. Also, minor suggestion, as a convention, use all caps for global variables – Rajesh Jul 27 '20 at 06:14
  • 2
    I made your code into a runnable snippet and as you can see, it does indeed log _"woof"_ – Phil Jul 27 '20 at 06:16
  • 1
    Confirmed it works in a snippet. Needs more detail. – lux Jul 27 '20 at 06:17
  • @Phil if you use a builder, they pass global scope as `undefined`. So unlike browser, it will never point to window – Rajesh Jul 27 '20 at 06:17
  • @Rajesh in that case, your question is lacking detail. Please improve it – Phil Jul 27 '20 at 06:18
  • Shared mutable state is said to be the root of al evils, so stay clear. Ja ja ja! – snnsnn Jul 27 '20 at 06:28
  • 1
    There is no need to -1 this question, I am bumping it up +1 – omt66 Jul 27 '20 at 06:28
  • Does this answer your question? [How do JavaScript closures work?](https://stackoverflow.com/questions/111102/how-do-javascript-closures-work) – Silviu Burcea Jul 27 '20 at 06:57

4 Answers4

3

It is called execution context. this inside talk function of dog object refers to dog rather than global object. To refer to global objects anywhere in script use globalThis instead of this

var sound = 'woof' //global variable
let dog = {
  //sound: 'woof'
  talk: function() {
   // this Refers to dog or depends on execution context
    console.log(globalThis.sound)
  }
}

let talkFunction = dog.talk
talkFunction() // result is woof
neotam
  • 2,611
  • 1
  • 31
  • 53
0

Just remove the this.. Global is not this. this is the object of the method, you have called.

var sound = 'woof' //global variable
let dog = {
  //sound: 'woof'
  talk: function() {
    console.log(sound)
  }
}

let talkFunction = dog.talk
talkFunction() // result is undefined
ceving
  • 21,900
  • 13
  • 104
  • 178
0

You can use the Arrow functions to get access to the parent object which is the window in this case. Keep in mind that you can't access the window in the 2 level nested objects because arrow function hasn't this and this represented to the parent object.

var sound = 'woof' //global variable
let dog = {
  //sound: 'woof'
  talk: () => {
    console.log(this.sound)
  }
}

let talkFunction = dog.talk
talkFunction() // result is undefined
Ali Torki
  • 1,929
  • 16
  • 26
0

No matter what language, I really recommend not to use globals this way. It will only bring you pain due to unnecessary dependencies across components, bad code readabilty and bad testability, just to name a few.

Why not change your code like this:

let dog = {
  talk: function(sound) {
  console.log(sound)
  }
}

const sound = 'woof' //global variable
let talkFunction = dog.talk
talkFunction(sound)

Now your talk function is not dependent on any global context and simply accepts the sound to make as a parameter.

Andreas Hütter
  • 3,288
  • 1
  • 11
  • 19