Link to home
Start Free TrialLog in
Avatar of elepil
elepil

asked on

JavaScript scope question

My question is based on the following code snippet:
<!DOCTYPE html>
<html>
<head>
<title></title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script>
    $(function() {
        function Test() {

            function innerTest() {
                sayHello("Saying hello from innerTest!");
            }
            
            // I put a 'this' on sayHello() to make it a public method outside of this constructor
            // function, without it, I won't be able to access it outside. But by using 'this', 
            // it no longer becomes accessible to innerTest() above. If take out the 'this', 
            // it will be accessible.
            this.sayHello = function(s) {
                console.log(s);
            }
            
            innerTest();
        }
        
        var t = new Test();
        
        t.sayHello("I'm the sayHello() function.");
        
    });

</script>
<style>
</style>
</head>
<body>    
</body>
</html>

Open in new window


I guess what is confusing me is that I always thought that the sayHello() and this.sayHello() would still be identical in scope, i.e, function scope. Apparently not. So can someone differentiate to me the scope differences between this.sayHello() and simply sayHello()?
Avatar of Bob Learned
Bob Learned
Flag of United States of America image

I find "this" in JavaScript, to be confusing.

this Operator
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this

A function's this keyword behaves a little differently in JavaScript compared to other languages. It also has some differences between strict mode and non-strict mode.

I would think that you would need "this" in the call:

this.sayHello("Saying hello from innerTest!");

Open in new window

Avatar of elepil
elepil

ASKER

Bob Learned, thanks for responding.

If you tried to run the code, you will know using this.sayHello() inside InnerTest() would generate an error "Uncaught TypeError: this.sayHello is not a function".

Besides, what I was really after was an explanation why this is happening the way it is.
SOLUTION
Avatar of Member_2_248744
Member_2_248744
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of elepil

ASKER

Slick812, thank you for responding.

I'm not sure I made my question clear, so let me restate, and I hope you will have the patience to copy/paste my very brief code snippet and try out what I'm going to say so you will know exactly what I'm talking about. Look at this excerpt of code:

function innerTest() {
                // This will work, innerTest() will be able to see the sayHello function definition
                sayHello("Saying hello from innerTest!");
            }
            
            sayHello = function(s) {
                console.log(s);
            }

Open in new window


Now look at this:

function innerTest() {
                // We put a 'this' in front of sayHello() definition, now this WON'T WORK anymore.
                sayHello("Saying hello from innerTest!");
            }
            
            // Because I added 'this', innerTest() above can't find it anymore
            this.sayHello = function(s) {
                console.log(s);
            }

Open in new window


The way I see it, there are only THREE scopes we are talking about here:

Global Scope (the scope of the constructor function Test())
        Function Scope (the scope of sayHello()=function.... )
            Inner function scope (the scope of innerTest()) 

Open in new window


It puzzles me why innerTest() could see sayHello() when it didn't have 'this', and then would totally fail to see it when it has a 'this'. There are only 3 levels of scopes that I can see in my example, but it is behaving as if there is a fourth scope that I'm not seeing.

So Slick812, do you see what I'm asking now?
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of elepil

ASKER

Steve Bink, your explanation and the links you provided gave me an epiphany on how JavaScript handles scoping.

I now realize private functions can only access private properties and private methods. They CANNOT access public properties and public methods by default. In order for private functions to access public properties, a closure has to be created to bridge the gap between private and public, as in your example when you created var $this = this.

Thanks for your help.