1

In the book JavaScript Enlightenment (the link is to a pre-published version (page 85), but I have the published version (Chapter 6.3) and it says the same thing), it says that any inner function will treat this as the global object (window) in ECMA-3, but will be fixed in ECMA-5.

The code is below:

http://jsfiddle.net/javascriptenlightenment/9GJhu/

var myObject = {
    func1: function() {
        console.log(this); // logs myObject
        var func2 = function() {
            console.log(this) // logs window, and will do so from this point on
            var func3 = function() {
                console.log(this); // logs window, as it’s the head object
            }();
        }();
    }  
}

myObject.func1();

But I thought the current Chrome, Firefox, and node.js should be implementing ECMA-5 to a large degree, so I tried the above code in them and they still print out the global object inside of func2 and func3. I then added "use strict"; to func1 and just in case, also to func2 and func3. The code: http://jsfiddle.net/9GJhu/6/ Now in Chrome and node.js, the this will get printed out as undefined, instead of myObject. So according to the book, this should be myObject in ECMA-5. What is wrong in the code above?

nonopolarity
  • 146,324
  • 131
  • 460
  • 740

3 Answers3

2

I might be wrong, but I haven't seen anywhere in the spec what that book is implying.
According to the ECMAScript 5.1 specification 10.4.3 Entering Function Code

  1. If the function code is strict code, set the ThisBinding to thisArg.
  2. Else if thisArg is null or undefined, set the ThisBinding to the global object.
  3. Else if Type(thisArg) is not Object, set the ThisBinding to ToObject(thisArg).
  4. Else set the ThisBinding to thisArg.
  5. Let localEnv be the result of calling NewDeclarativeEnvironment passing the value of the [[Scope]] internal property of F as the argument.
  6. Set the LexicalEnvironment to localEnv.
  7. Set the VariableEnvironment to localEnv.
  8. Let code be the value of F‘s [[Code]] internal property.
  9. Perform Declaration Binding Instantiation using the function code code and argumentsList as described in 10.5.

According to (1.), since your func2 and func3 don't have any context, and you specified strict mode your context will be set to undefined. Without strict mode and according to (2.) this will be set to window.

ArtBIT
  • 3,931
  • 28
  • 39
1

When you use the 'use strict' directive, the 'this' keyword is 'undefined' by default, as opposed to non-strict mode, where the 'this' keyword refers to the Global Object by default. You need to explicitly specify the context.

On a side note, you should only need to declare 'use strict' once.

Dzulqarnain Nasir
  • 2,150
  • 1
  • 19
  • 16
0

The fact that the functions are nested doesn't mean any thing. They keep working the same way also not nested:

var myObject = {
    func1: function() {
        console.log(this); // logs myObject
    }  
}
myObject.func1();

var func2 = function() {
    console.log(this) // logs window, and will do so from this point on
}();

var func3 = function() {
    console.log(this); // logs window, as it’s the head object
}();

http://jsfiddle.net/NYr3y/2/

var myObject = {
    func1: function() {
        "use strict";

        console.log(this); // logs myObject
    }  
}

myObject.func1();


var func2 = function() {
    "use strict";

    console.log(this) // logs window, and will do so from this point on

}();

var func3 = function() {
    "use strict";

    console.log(this); // logs window, as it’s the head object
}();

http://jsfiddle.net/4B84u/2/

The first function are called with a context (as a method) and so then "this" is myObject.

the other functions are called without a context ( just like func2() ) and in this case ECMA-5 does not allow not explicit reference to the global object nether through this.

Most browsers does not apply ECMA-5 by default because is not retro-compatible since more restrictive.

Plap
  • 1,046
  • 1
  • 8
  • 14