0

I am currently reading the book "Javascript: The Good Parts" and was playing with Functions. I produced a test script to test some properties and I am somewhat confused by the results. Here is the code:

<h3>Object</h3>
        <div style="padding-left: 10px;">
            <script type="text/javascript">
                function outterF()
                {
                    document.writeln("outterF.this = " + this + "<br>");

                    function innerF() 
                    {
                        document.writeln("innerF.this = " + this + "<br>");
                        return this;
                    };

                    var inner = innerF();
                    return this;
                }

                document.writeln("<b>From Inside:</b><br>");
                var outF = outterF();
                var inF = outF.inner;

                document.writeln("<br>");
                document.writeln("<b>From Outside:</b><br>");
                document.writeln("outterF.this = " + outF + "<br>");
                document.writeln("innerF.this = " + inF + "<br>");
            </script>
        </div>

Result is:

Object
From Inside:
outterF.this = [object Window]
innerF.this = [object Window]

From Outside:
outterF.this = [object Window]
innerF.this = undefined

Notice that outF.inner returns "undefined", is that some kind of a language bug?
Obviously, outF.inner points to Window object that has nothing to do with my object but shouldn't it be at least pointing to a Function object instead?

Thanks
-Assaf

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
Assaf Moldavsky
  • 1,681
  • 1
  • 19
  • 30

6 Answers6

7

This is how the value of this is determined.

// function case
foo(); // this inside foo will refer to the global object

// method case
test.foo(); // this inside foo will refer to test

// constructor case
new foo(); // this inside foo will refer to the newly created object

So unless you deal with a method or a constructor this is rather useless.

Ivo Wetzel
  • 46,459
  • 16
  • 98
  • 112
  • Ok so when I execute "var outF = outterF();" doesn't that create a Function object, which has a property "inner" that point to another Function object? Why is isn't "outF.inner" a "method case" invocation? – Assaf Moldavsky Dec 26 '10 at 04:05
  • Because you're not using the `new` keyword, therefore you're not invoking `outterF` as a constructor, you're rather calling it as a simple function. – Ivo Wetzel Dec 26 '10 at 04:07
2
outF.inner

points to a variable that is not accessible in that scope from where line of code is.

inner is declared in outterF and it's only accessible in there.

If you used

this.inner = innerF();

it may be accessible (can't test right now)

sjngm
  • 12,423
  • 14
  • 84
  • 114
1

'this' is a keyword not a property so you need to reference it as a standalone semantic:

//correct syntax...that gets value of this keyword
var that = this 

//unusual syntax...that is undefined, unless you explicitly set foo.this earlier
vat that = foo.this; 

Specifically a 'this' value is assigned for every runtime function context (and the global context). It is immutable within a give context. The rules are somewhat complex but the important cases are...

In global context 'this' will always be the global object (e.g. window)

var that = this; //window

When invoked from a method call 'this' will be the receiver of the method call

obj.foo = function() {
    return this;
}

obj.foo(); //obj

When invoked from a function call 'this' will be the global object

var obj = {};
obj.foo = function() {
    return this;
}

var myFn = obj.foo;
myFn(); //window

You can also use call/apply to set a custom 'this' value within a function context. If you're interested in learning more read this: (no pun :-) ) http://javascriptweblog.wordpress.com/2010/08/30/understanding-javascripts-this/

AngusC
  • 628
  • 5
  • 9
  • Well when I asked that question I was a JS noob pretty much, I have done some crazy and complex JS development since then and all this now just looks like kids stuff to me when I look back. These days if I want to set the "this" var I just use call or apply on the function (or closures). Thank you for taking the time to answer. – Assaf Moldavsky Jun 26 '11 at 04:11
0

outF is [object Window] and doesn't have a "inner" variable, as such if inF = outF.inner, it's undefined

Mantar
  • 2,710
  • 5
  • 23
  • 30
0

Note that outF (in the line outF.inner) doesn't refer to outF's scope, but rather the value assigned to outF.

function MyCtor() {
    this.someVal = function() {
        document.write("someVal's this? " + this);
    };
}

var myobj = new MyCtor();
myobj.someVal();

Gives someVal's this? [object Object] (or whatever), which is what you want.

Asherah
  • 18,948
  • 5
  • 53
  • 72
  • Yes that is because you've used the constructor invocation method "NEW", which works. There are four ways of invocation (according to the book) - "Method Invocation", "Function invocation", "Constructor Invocation" (what you have used), and "Apply Invocation". I am struggling with the Function and Method invocations. – Assaf Moldavsky Dec 26 '10 at 04:18
0

Ok so apparently I was invoking the functions incorrectly... (thanks to Ivo Wetzel for pointing out). Changing the code to this looks better:

<h3>Object</h3>
        <div style="padding-left: 10px;">
            <script type="text/javascript">
                var outF = function outterF()
                {
                    var that = this;
                    function getThat() {return that;}

                    document.writeln("outterF.this = " + this + "<br>");

                    var inner = function innerF() 
                    {
                        document.writeln("innerF.this = " + this + "<br>");
                        return this;
                    };


                    document.writeln("inner is " + typeof inner + "<br>");

                    return this;
                }

                document.writeln("<b>From Inside:</b><br>");
                var inF = outF.inner;

                document.writeln("<br>");
                document.writeln("<b>From Outside:</b><br>");
                document.writeln("outterF.this = " + typeof outF + "<br>");
                document.writeln("innerF.this = " + typeof inF + "<br>");
            </script>
        </div>

Result:

Object
From Inside:

From Outside:
outterF.this = function
innerF.this = undefined
Assaf Moldavsky
  • 1,681
  • 1
  • 19
  • 30