-1

when foo() gets called, "this" inside foo function is referring to Global scope and "bar" variable has already being defined and get assigned a value of "bar".

so why inside foo(), "this.bar" gives undefined value but bar does not.

function foo(){
  this.baz = "baz";
  console.log(this.bar + " " + baz);  //undefine  baz
   console.log( bar + " " + baz);  //bar   baz
 }
var bar="bar";
foo();
Rita
  • 1
  • 1

2 Answers2

1

so why inside foo(), "this.bar" gives undefined value but bar does not.

Probably your var bar="bar"; is not actually in the global scope. If it was your code would work as shown. Referencing bar will find a variable in any parent scope. But, this.bar when this is set to the global object requires a bar that is defined in the global scope. So, we conclude that var bar="bar"; is not actually in the global scope.


When you make a normal function call and you are not running in strict mode, this will be set to the global object which is window in a browser. In general, this is NOT a recommend use of this and, in fact, it will break in strict mode. But, I will explain what's going on in your code.

In your specific example, you can replace this with window and your code is essentially doing this:

function foo(){
    window.baz = "baz";
    log(window.bar + " " + baz);
    log(bar + " " + baz);  //bar   baz
} 

window.bar="bar";
foo();


// display output
function log(x) {
    var div = document.createElement("div");
    div.innerHTML = x;
    document.body.appendChild(div);
}

And, here's the version when using this:

function foo(){
    this.baz = "baz";
    log(this.bar + " " + baz);
    log(bar + " " + baz);  //bar   baz
} 

bar="bar";
foo();


// display output
function log(x) {
    var div = document.createElement("div");
    div.innerHTML = x;
    document.body.appendChild(div);
}

And, as you can see, there is no undefined value when you run either snippet.


If you run your code in strict mode (which is highly recommended), then this will be set to undefined in a normal function call and your code will fail. Instead, only use this when you know it has specifically been set to a value you want such as in a constructor function called with new or in a method call or in a callback that is specifically setting this to a known value (probably with .call() or .apply()).

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • why my original code doesn't work before replacing "this" with window? – Rita Mar 15 '16 at 18:33
  • @Rita - See the part of my answer I added to the beginning. Because your `var bar="bar";` is not actually in the global scope. Is this is in a jsFiddle by any chance? – jfriend00 Mar 15 '16 at 18:34
  • sorry I take this back. – Rita Mar 15 '16 at 18:37
  • Yes I was running it in jsFiddle. Now that I ran it on CodePen or Plunker., they both give me the "bar baz" value no matter if I use this keyword or window keyword. – Rita Mar 15 '16 at 18:40
  • @Rita - The default in jsFiddle puts your code inside an `onload` event handler. If you click on the "Javascript" button and change the "load type" to "No wrap - in ", then your code will be in the global scope as you can see here: https://jsfiddle.net/qbtnx8a7/ – jfriend00 Mar 15 '16 at 18:50
0

In javascript when a function is defined in the global scope, like you have in your example, the value of this is the global object. In your case because bar is defined globally it is accessible through this.bar within the foo() function.

bwegs
  • 3,769
  • 2
  • 30
  • 33
  • It doesn't matter whether the function is defined in the global scope or not. Any plain function call will set `this` to the global object when not in `strict` mode or will set `this` to `undefined` in `strict` mode. – jfriend00 Mar 15 '16 at 18:26
  • @jfriend00 Then why doesn't `var obj = { me: function () { console.log(this); } };` log `window`? – bwegs Mar 15 '16 at 18:29
  • Because that's a method call and `obj.method()` sets `this` to `obj`. See this other answer for more info: [The 5 ways that `this` is set in Javascript](http://stackoverflow.com/questions/28016664/when-you-pass-this-as-an-argument/28016676#28016676). `obj.method()` is not a plain function call. – jfriend00 Mar 15 '16 at 18:36