6

Tested some js code in Chrome Dev Console and I'm a bit confused.

I know that in strict mode functions that are not methods of an object when referred to this keyword should receive undefined instead of global object.

function test(){
    "use strict";
    return this===undefined;}
test(); 

Outputs false.

"use strict";
function test(){
    return this===undefined;}
test(); 

Still false.

(function test(){
    "use strict";
    return this===undefined;}());

Outputs true.

Just wanted to clarify. ʕ •ᴥ•ʔ I'm new to js.

3 Answers3

3

What you have noticed is simply a side-effect of the way the developer console works. When you enter code there, this is effectively what happens (see this answer for more details):

eval.call(null, "with (window) { \
                     function test() { \
                         'use strict'; \
                         console.log(this); \
                     } test(); \
                 }");

This is an indirect call to eval, which means it will always execute in the global execution context (in the browser, that's window).

Effectively, the function is bound to the global object and therefore this holds a reference to the global object, as if you did this in a web page (rather than in the console):

function test(){
    "use strict";
    return this === undefined;
}

test(); // true
test.call(window); // false
Community
  • 1
  • 1
James Allardice
  • 164,175
  • 21
  • 332
  • 312
  • 1
    An object like that referred to by `window` *is* *not* an execution context. An execution context is an abstract program entity; it has a *scope chain* with objects in it. In this case, it would be the `with` statement that inserts the object referred to by `window` in the scope chain for the context of the `test()` call. – PointedEars Feb 28 '13 at 12:58
  • @PointedEars - Yes, of course. I could have said "the lexical environment's environment record to which the `window` object belongs" but the way I put it was simpler and I think still gets the point across. And the `with` statement makes no difference in this case - it's the way that `eval` is called that affects the context in which its argument is evaluated. – James Allardice Feb 28 '13 at 13:11
  • The `with` statement here *might* be substantial; it certainly is if you assume (IMO mistakenly) that the `window` host property of the global object always refers to the global object. Because then the `test()` call would be equivalent to `global.window.test()`, where `global` would be a stand-in for the standard reference to the global object. – PointedEars Mar 01 '13 at 00:52
1

Everything's fine. If you run your code via some HTML page (not a dev console), results meet expectations (always this===undefined).

Additionally in latest Firefox (Firebug):

function test(){
    "use strict";
    return this===undefined;}
test(); 
>> true

So this seems to be just another Chrome's bug (feature?). It feels like it has a slightly different approach to the code that is passed via dev console.

Also note that order matters:

<script>
    console.log( 'Me First!' );

    "use strict";

    function test(){
        console.log( this );
    }
    test();

</script>

>>> "Me First!"
>>> Window {top: Window, window: Window, location: Location, external: Object, chrome: Object…}

But:

<script>
    "use strict";

    console.log( 'Me later!' );

    function test(){
        console.log( this );
    }
    test();

</script>

>>> undefined
>>> "Me later!"
oleq
  • 15,697
  • 1
  • 38
  • 65
1

It is a bug in the Chromium Developer Console that causes this to still refer to the global object. The same code works as specified with javascript: in the location bar, and in documents.

You can test that like so (2 console inputs):

var global = (function () { return this; }());

"use strict";
function test () { return this === global; }
test();

and (one or more console inputs)

var script = document.createElement("script");
script.type = "text/javascript";
script.appendChild(document.createTextNode(
  'function test () { "use strict"; return this === undefined; }; console.log(test());'
));
document.body.appendChild(script);

Tested in Chromium Version 25.0.1364.97 Debian 7.0 (183676).

PointedEars
  • 14,752
  • 4
  • 34
  • 33
  • Your first test is a broken test. Even if you run that in a script tag instead of the console, you will still get `true`, because `"use strict"` must be the *first* line in it's scope. Your example has it coming after `var global ...`, so the directive is ignored (as per the spec). – Nathan Wall Mar 02 '13 at 01:52
  • @NathanWall No, see my clarification. I suggest you use `debugger;` in the function to inspect the call stack. – PointedEars Mar 03 '13 at 12:27