【问题标题】:JavaScript 'use strict'; inside functionsJavaScript '使用严格';内部函数
【发布时间】:2013-02-14 15:16:13
【问题描述】:

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

我知道在 严格模式 中,当引用 this 关键字时不是对象方法的函数应该接收 undefined 而不是全局对象.

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

输出 false

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

仍然错误

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

输出 true

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

【问题讨论】:

标签: javascript ecmascript-5 strict


【解决方案1】:

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

另外在最新的 Firefox (Firebug) 中:

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

所以这似乎只是另一个 Chrome 的错误(功能?)。感觉它对通过开发控制台传递的代码的处理方式略有不同。

还要注意顺序很重要:

<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!"

【讨论】:

    【解决方案2】:

    您注意到的只是开发人员控制台工作方式的副作用。当您在那里输入代码时,实际上会发生这种情况(有关更多详细信息,请参阅this answer):

    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
    

    【讨论】:

    • window 引用的对象 不是执行上下文。执行上下文是一个抽象的程序实体;它有一个作用域链,里面有对象。在这种情况下,将是 with 语句将 window 引用的对象插入到 test() 调用上下文的作用域链中。
    • @PointedEars - 是的,当然。我可以说“window 对象所属的词法环境的环境记录”,但我说它的方式更简单,我认为仍然可以理解这一点。在这种情况下,with 语句没有任何区别——eval 的调用方式会影响评估其参数的上下文。
    • 这里的with 声明可能很重要;如果您假设(IMO 错误地)全局对象的 window 主机属性总是引用全局对象,那肯定是这样。因为这样test() 调用将等效于global.window.test(),其中global 将是对全局对象的标准引用的替代。
    【解决方案3】:

    这是 Chromium 开发者控制台中的一个错误,导致 this 仍然引用全局对象。与地址栏和文档中的javascript: 指定的代码相同。

    您可以这样测试(2 个控制台输入):

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

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

    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" 必须是其范围内的 first 行。您的示例在var global ... 之后出现,因此该指令被忽略(根据规范)。
    • @NathanWall 不,请参阅我的说明。我建议你在函数中使用debugger; 来检查调用堆栈。
    猜你喜欢
    • 2018-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-08
    • 2011-08-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多