JavaScript函数内的'use strict';是什么意思?

6

我在Chrome Dev Console中测试了一些js代码,感到有点困惑。

我知道在严格模式下,不是对象方法的函数被引用时,应该接收undefined而不是全局对象。

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

输出结果为 false
"use strict";
function test(){
    return this===undefined;}
test(); 

仍然是false

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

输出true

只是想澄清一下。ʕ •ᴥ•ʔ 我是js的新手。


2
请阅读类似的问题:https://dev59.com/ynM_5IYBdhLWcg3wiDuA它询问了在JavaScript中使用"use strict"是什么意思以及背后的原因。 - Nick Andriopoulos
4
@hexblot这并没有回答问题... - Christoph
3个回答

3
你所注意到的只是开发者控制台工作方式的一个副作用。当你在那里输入代码时,实际上会发生以下事情(有关更多详细信息,请参见此答案):
eval.call(null, "with (window) { \
                     function test() { \
                         'use strict'; \
                         console.log(this); \
                     } test(); \
                 }");

这是对eval间接调用,这意味着它将始终在全局执行上下文中执行(在浏览器中,即window)。
实际上,该函数被绑定到全局对象,因此this持有一个全局对象的引用,就好像您在网页中执行一样(而不是在控制台中执行)。
function test(){
    "use strict";
    return this === undefined;
}

test(); // true
test.call(window); // false

1
类似于“window”所指的对象不是执行上下文。执行上下文是一个抽象的程序实体;它具有一个包含对象的作用域链。在这种情况下,是“with”语句将由“window”引用的对象插入到test()调用的上下文的作用域链中。 - PointedEars
@PointedEars - 当然可以。我本来可以说“window对象所属的词法环境的环境记录”,但我这样说更简单,而且我认为仍然能够表达出重点。在这种情况下,with语句没有任何影响——影响其参数求值上下文的是调用eval的方式。 - James Allardice
这里的with语句可能很重要;如果你假设(在我看来是错误的)全局对象的window宿主属性总是指向全局对象,那么它肯定是重要的。因为这样,test()调用将等同于global.window.test(),其中global将作为对全局对象的标准引用的替身。 - PointedEars

1

一切都很好。如果您通过某个HTML页面(而不是开发控制台)运行代码,则结果符合预期(始终为this === undefined)。

此外,在最新的Firefox(Firebug)中:

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

这似乎只是Chrome的另一个bug(特性?)。感觉它对通过dev控制台传递的代码有稍微不同的处理方式。
另外请注意顺序的重要性:
<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…}

但是:
<script>
    "use strict";

    console.log( 'Me later!' );

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

</script>

>>> undefined
>>> "Me later!"

1
这是Chromium开发者控制台中的一个错误,导致this仍然指向全局对象。在地址栏中使用javascript:和文档中,相同的代码按规定工作。
您可以这样测试(2个控制台输入):
var global = (function () { return this; }());

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

和(一个或多个控制台输入)

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

在Chromium版本25.0.1364.97 Debian 7.0 (183676)中进行测试。


你的第一个测试是一个失败的测试。即使你在脚本标签中运行它而不是控制台,你仍然会得到 true,因为 "use strict" 必须是其作用域中的第一行。你的示例在 var global ... 之后才出现,所以该指令被忽略(根据规范)。 - Nathan Wall
@NathanWall 不是的,请看我的澄清。我建议您在函数中使用 debugger; 来检查调用堆栈。 - PointedEars

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接