严格模式是否更高效?

81

一般情况下,在浏览器中执行JavaScript时是否启用“严格模式”会使其性能更好?主流浏览器是否做了额外的优化或使用其他技术以提高在严格模式下的性能表现?

稍微改述一下,严格模式是否旨在允许浏览器引入额外的优化或其他性能增强措施,除了其它目标之外?


现在有哪些浏览器支持ECMAScript 5呢? - Jamie Wong
3
@Jamie http://kangax.github.com/es5-compat-table/ - Matthew J Morrison
谢谢。根据这个来看,“严格模式”的性能在浏览器中暂时不会有太大影响。 - Jamie Wong
4
@Matthew: 不错的链接!@sje397: 在那个列表上,唯一完整的 ECMAScript 5 实现是 BESEN(我之前也没听说过),它的主页上注意到了以下内容:“严格模式比非严格模式运行更快,请尽可能使用‘use strict’”。 - Crescent Fresh
2
据我所知,Douglas Crockford 在他的某个演讲中声称(链接:http://www.youtube.com/watch?v=hQVTIJBZook),`with` 关键字不仅性能差,而且仅仅是将其包含在语言中就会使整个语言变慢。CMS 的回答中提到的这个链接(http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/)说 with 关键字在严格模式下不起作用,因此这至少表明了一些加速的潜力 - Tyler
显示剩余2条评论
4个回答

30

严格模式是否旨在允许浏览器引入其他优化或性能增强措施,除了其其他目标之外?

我不确定它是否是有意为之,但我认为答案是肯定的。

但我可以肯定地说,严格模式确实提供了这些机会,浏览器将实现它们,无论ECMA委员会是否有意提供这些机会。然而,我不希望所有这些机会立即被利用。在许多情况下,口号很可能是正确性先行,性能以后,因为现在严格模式并没有被广泛使用。 (我在Mozilla的JavaScript引擎上工作,并实现了严格模式的各个部分,我们通常会按照这种方式来实现--尽管如果我试图想出一个或两个例外,我可能会找到。)


4
是的,严格模式的设计目标是启用词法作用域(这就是为什么禁用了像with这样的内容)。从一开始就是这个意图。 - Benjamin Gruenbaum

23

严格模式并不是关于性能的问题,它是语言的一种严格变体,其主要目标是避免被认为是容易出错的特性

基本上,它的目的是使语言更加安全,引入了很多语义上的改变,还增加了额外的错误检查,而且如果有错误,会有响应的提示。在非严格代码中,事情只会悄悄地失败。

至于性能方面,我认为浏览器厂商现在正在努力实现严格模式,问题在于JS引擎大多基于ECMAScript 3,实现严格模式并不容易,因为严格性的范围非常灵活,您可以混合非严格和严格代码。

另请参阅:


+1 for the links. 我不太明白第三句话与性能有什么关系。 - sje397
4
“约翰·雷西格(John Resig)没有提到的是,严格模式可能会带来更好的性能。如果浏览器被告知“我声明这段代码是好的和正确的”,它就可以花更少的时间处理不明确的事情,然后专注于手头的业务。” - sje397
@sje397:strict 模式的另一个好处是,如果一个函数声明了一个本地变量 foo,并且没有定义任何捕获它的嵌套函数,那么在第一次读取 foo 之前,它会将一个数字存储到 foo 中,并且永远不会将除数字以外的任何东西存储到 foo 中,因此被调用的函数(或其他任何东西)无法使 foo 保存除数字以外的任何东西。很容易确定上述条件是否成立,并且使用数字可以比使用偶然是数字的多态对象更容易快速地完成工作。 - supercat

14
根据该测试,“严格模式”可能快约25%。
<div id="a">
  Q
</div>
<div id="b">
  Q
</div>
<script>
  Benchmark.prototype.setup = function() {
    function d(i) {
      var x = '999';
      y = eval("y = 8;");
      var z = x + y + i;
      document.getElementById('a').innerHTML = z;
    }

    function c(i) {
      'use strict'
      var x = '999';
      var y = eval("y = 8;");
      var z = x + y + i;
      document.getElementById('b').innerHTML = z;
    }
  };
</script>

这里可以进行测试: http://jsperf.com/strict-mode


有趣的是,在“严格模式”下,对参数数组的操作速度可以快大约6倍!

<script>
  Benchmark.prototype.setup = function() {
    var nonstrict = (function() {
        return function (arg1) {
            var index;
            for (index = 1; index < arguments.length; ++index) {
                arguments[0] += arguments[index];
            }
            return arguments[0] - arg1;
        };
    }());
    var strict = (function() {
        "use strict";
        return function (arg1) {
            var index;
            for (index = 1; index < arguments.length; ++index) {
                arguments[0] += arguments[index];
            }
            return arguments[0] - arg1;
        };
    }());
    var result;
  };
</script>

这是 jsPerf 测试:http://jsperf.com/strict-mode-arguments


2
在我的Chrome浏览器上,今天的2017年,在你的基准测试中,非严格版本分别比严格版本慢约15%和70%。我猜这意味着性能差异比以前小了,但仍然相当显着。有什么想法造成这些性能差异吗? - John Slegers

3

大部分情况下不会。如果您仔细研究 ECMAScript 5 标准文档,您会发现几乎所有伪代码算法中出现的 Strict Mode 都是这样:

  if (isStrictMode) {
      //throw an (early) SyntaxError or TypeError
  }
  else {
      //return
  }

以下有两点需要注意:

  1. 在ECMAScript 3中,严格模式的检查不存在。虽然它相对较轻,但符合JavaScript规范的实现现在与其ECMAScript 3版本相比至少要运行一个额外的条件检查。是的...我知道像这样的单个检查会烧掉很少的时钟周期,但是小事情会累加。
  2. 由于严格模式主要是JavaScript的解析时特性,因此当某个网站启用严格模式(例如SunSpider)时,您喜欢的浏览器不会显示太多性能下降。也就是说,性能下降发生在代码执行之前,这意味着它可能会被最终用户感知,但使用“Date”对象来测量块执行时间时基本上无法测量。

2
但是你怎么知道例如v8不会利用严格模式进行额外的优化呢? - UpTheCreek
6
我曾参与测试Internet Explorer 10严格模式的性能,还有其他事情。我能给你的最好例子是,如果你有两个完全相同的大型JavaScript文件,并且没有严格模式违规,而且只有其中一个包含"use strict",那么没有"use strict"的那个文件会更快运行,因为它不需要运行严格模式检查。即使在严格模式中删除对'with'的支持,也不能将其从解析器中彻底删除(仍然必须允许它在非严格模式下使用)。不,相反,你的DLL大小实际上已经增加了,执行时间也增加了。 - Dave

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