7

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.

2

3 Answers 3

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 
Sign up to request clarification or add additional context in comments.

3 Comments

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 - 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.
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.
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).

2 Comments

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).
@NathanWall No, see my clarification. I suggest you use debugger; in the function to inspect the call stack.
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!" 

Comments