JavaScript的严格模式是如何实现的

How is JavaScript's strict mode implemented

本文关键字:何实现 实现 模式 JavaScript      更新时间:2023-09-26

>更新:

也许调用函数的方式是罪魁祸首,所以这里是:

2 个 JS 文件
  主.js:自调用(非严格)函数,为"(on)load"事件添加事件侦听器。
回调调用加载器函数,该函数解析 location.pathname,并调用 init 函数,并分离/删除"(on)load"侦听器并返回 null(显式)。

  PageSpecific.js:包含_init函数,向正文添加几个事件侦听器。
其中一个侦听器的回调(也从闭包返回)调用使用 argument.callee 作为递归引用的严格函数。
返回事件处理程序的闭包可能 - 取决于浏览器 - 或者可能不会绑定和解绑其他事件,但我认为这在这里无关紧要,因为这是模仿 IE 中的 onchange 事件<9

我希望这是相当清楚的,所以它:
匿名。 F => 事件侦听器 =>处理程序(命名但在 anon F 中声明)=> 页面加载器 =>                   
初始化 => 事件监听器
             
                  闭包
                      返回的绑定函数 => 调用严格函数

顺便说一下:这是我实际使用的调用的_init函数的精简版本。更具体地说:将事件侦听器和 - 处理程序绑定在一起的闭包。这是我的另一个长问题,似乎没有人知道答案......提示 ;-)


我正在调试一些相当大的(和复杂的)JavaScript。在这样做的过程中,我注意到我有一个函数,使用严格模式,工作正常,但如果我没记错的话,应该抛出错误。由于脚本相当大且复杂(事件委派、堆叠闭包等),因此这里有一个简单的示例:

function withCalleeRecursion(foo)
{
    'use strict';//strict throws typeError on arguments.callee
    foo = foo.replace(/(a|b)+/gi, function (p1,p2)
    {
        if (p1.match(/(a|b){2,}/i))
        {
            return p1.replace(/(a|b)/gi,arguments.callee);//no errors
        }
        return (p2.match(/a/i) ? 'X':'Y');
    });
    return foo;
}
(function()
{//not strict
    alert(withCalleeRecursion('Abba makes me barf'));
})();

在我的实际脚本中,这工作得很好。但是,当我将其粘贴到Firebug和chrome控制台中时,会抛出错误。我在这里尝试了这段代码,所以 IE 也应该抛出错误,但是当我在 IE 的调试器中运行代码时,它工作得很好。据我所知,更改文档类型(尝试过 html5 和 html4)没有区别。

我是否正确认为(大多数)浏览器对 'use strict'; 指令并不像它的名字所暗示的那样严格?当解析脚本时检测到可能的错误时,浏览器似乎选择忽略它。这是真的吗?


同时,出于预防措施,我对功能进行了轻微更改。由于我在这里看到了很多人们想知道如何在严格模式下获取callee引用的问题,所以我也将其粘贴在这里:

function withCalleeRecursion(foo)
{
    'use strict';
    foo = foo.replace(/(a|b)+/gi, function abR(p1,p2)
    {
        if (p1.match(/(a|b){2,}/i))
        {
            return p1.replace(/(a|b)/gi,abR);
        }
        return (p2.match(/a/i) ? 'X':'Y');
    });
    return foo;
}

命名回调,仅此而已。

这可能是因为浏览器控制台使用 eval() ,这改变了事情。尽管将"use strict";放在传递给eval()的代码字符串的开头按预期工作,但控制台实现可能会将代码附加到您在控制台中键入的字符串中,这意味着"use strict";不再是执行的第一个语句,因此会被忽略。

以下文章中对此进行了引用和建议的解决方法:

http://javascriptweblog.wordpress.com/2011/05/03/javascript-strict-mode/

建议的解决方法是将控制台中的代码包装在立即执行的函数中:

(function() {
    "use strict";
    nonExistentVariable = 1; // Error is now thrown
})();

也许这篇文章可以帮助你了解更多。无论如何,解决方案就是您提到的解决方案,错误是因为访问 arguments.caller 和 arguments.callee 在严格模式下抛出异常。因此,需要命名要引用的任何匿名函数。