1

Can someone please explain the following behavior? The first 2 examples work as expected, but why doesn't the last example work? I want to understand what's going on when I omit the 'this' keyword. It seems like I was able to omit it in the first 2 examples.

Alerts hello:

$(document).ready(
    function()
    {
        hello = 'hello';

        function sayHello()
        {
            alert( this.hello );
        }

        sayHello();
    }
);

Alerts hello:

$(document).ready(
    function()
    {
        hello = 'hello';

        function sayHello()
        {
            alert( hello );
        }

        sayHello();
    }
);

Error on the alert statement: Uncaught ReferenceError: hello is not defined

$(document).ready(
    function()
    {
        this.hello = 'hello';

        function sayHello()
        {
            alert( hello );
        }

        sayHello();
    }
);
WhiteHat
  • 53,880
  • 7
  • 33
  • 116
Kacy
  • 3,018
  • 3
  • 24
  • 49
  • 1
    Because there is no local variable called `hello` – zerkms Sep 18 '15 at 23:00
  • 2
    It's the same reason this won't work `var hello = {x: 123}; alert(x);`. – Adrian Lynch Sep 18 '15 at 23:00
  • 3
    I think more interesting is why first example works. – Alexei Levenkov Sep 18 '15 at 23:03
  • possible duplicate of [How does the "this" keyword work?](http://stackoverflow.com/questions/3127429/how-does-the-this-keyword-work) – saj Sep 18 '15 at 23:03
  • 2
    @AlexeiLevenkov those are globals and there is no `strict mode` – zerkms Sep 18 '15 at 23:03
  • @zerkms Then why does the first example work? – Kacy Sep 18 '15 at 23:04
  • possible dup: [What is the scope of variables in JavaScript?](http://stackoverflow.com/questions/500431/what-is-the-scope-of-variables-in-javascript) – WhiteHat Sep 18 '15 at 23:07
  • 1
    @WhiteHat—the OP's confusion isn't about scope, it's because the jQuery *$(document).ready* function sets *this* as *document*, so *this.hello* creates a property of *document*, not the global object (aka *window* in a browser). – RobG Sep 18 '15 at 23:15
  • 1
    But, if we have function inside function (inside function), 'this' refers to global object (window): http://jsfiddle.net/va77ccx7/1/ Not sure if i am right.... – sinisake Sep 18 '15 at 23:19

2 Answers2

6

Global variables are automatically made properties of the window object. And when you call a function without specifying any context (i.e. as functionName() instead of something.functionName()), the default context is also the window object.

Your first function is setting the global variable hello, which is the same as window.hello. The sayHello() function then alerts this.hello, which is also the same as window.hello because this == window.

The third case is different because your outer function is being called by $(document).ready(). When jQuery calls an event handler function, the context is the target of the event. In this case, this == document, so when you do:

this.hello = 'hello';

it's equivalent to:

document.hello = 'hello';

This doesn't set the global variable hello, so sayHello doesn't access it. This will work equivalently:

$(document).ready(
    function()
    {
        this.hello = 'hello';

        function sayHello()
        {
            alert( document.hello );
        }

        sayHello();
    }
);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Barmar
  • 596,455
  • 48
  • 393
  • 495
0

In the first example when you say hello='hello' you are assigning a value to a variable hello.

So, if you alert(hello) it prints the variable.


When you say this.hello='hello' it assigns a property to the function. Since the function is a callback of $(document) it is assigning document.hello. In general however, it will just be the property of the anonymous function

cjds
  • 7,573
  • 9
  • 41
  • 75