非常教程

JavaScript参考手册

其他 | Miscellaneous

Strict mode: Transitioning to strict mode

ECMAScript 5引入了严格的模式,现在已经在所有主流浏览器(包括IE10)中实现。尽管使Web浏览器将代码解释为严格很容易(只需添加'use strict';源代码的顶部),但将现有代码转换为严格模式需要更多的工作。

本文旨在为开发人员提供指导。

逐渐过渡

严格模式的设计使其可以逐渐过渡到它。可以单独更改每个文件,甚至可以将代码转换为严格模式直至功能粒度。

从非严格到严格的差异

语法错误

添加'use strict';时,以下情况会SyntaxError在脚本执行前抛出一个:

  • 八进制语法 var n = 023;
  • with 声明
  • 使用delete一个变量名delete myVariable;
  • 使用evalarguments作为变量或函数参数名称
  • 使用新保留的关键字之一(在预知的ECMAScript的2015年): ,implementsinterfaceletpackageprivateprotectedpublicstaticyield
  • 以块的形式声明函数 if (a < b) { function f() {} }
  • 明显的错误
    • 在对象文字中为属性名称声明两次相同的名称{a: 1, b: 3, a: 7}ECMAScript 2015中不再是这种情况(错误1041128)。
    • 声明两个具有相同名称的函数参数 function f(a, b, b) {}

这些错误是很好的,因为它们揭示了简单的错误或不好的做法。它们发生在代码运行之前。

新的运行时错误

JavaScript曾经在所执行操作的上下文中以静默方式失败是一个错误。在这种情况下,严格模式会抛出。如果你的代码库包含这样的情况,测试将是必要的,以确保没有任何损坏。再一次,它可能发生在函数粒度级别。

将值设置为未声明的变量

function f(x) {
  'use strict';
  var a = 12;
  b = a + x * 35; // error!
}
f(42);

这用于更改全局对象上的值,这很少是预期的效果。如果您确实想为全局对象设置一个值,请将其作为参数传递并将其明确指定为属性:

var global = this; // in the top-level context, "this" always
                   // refers to the global object
function f(x) {
  'use strict';
  var a = 12;
  global.b = a + x * 35;
}
f(42);

试图删除一个不可配置的属性

'use strict';
delete Object.prototype; // error!

在非严格的情况下,这会默默地失败,与用户的期望相矛盾。

Poisoned arguments and function properties

访问arguments.calleearguments.calleranyFunction.caller,或anyFunction.arguments引发在严格模式错误。唯一合法的用例是重用一个函数,如下所示:

// example taken from vanillajs: http://vanilla-js.com/
var s = document.getElementById('thing').style;
s.opacity = 1;
(function() { 
  if ((s.opacity-=.1) < 0)
    s.display = 'none';
  else
    setTimeout(arguments.callee, 40);
})();

可以改写为:

'use strict';
var s = document.getElementById('thing').style;
s.opacity = 1;
(function fadeOut() { // name the function
  if((s.opacity-=.1) < 0)
    s.display = 'none';
  else
    setTimeout(fadeOut, 40); // use the name of the function
})();

语义差异

这些差异是非常微妙的差异。测试套件可能无法捕捉到这种微妙的差异。仔细检查你的代码库可能是必要的,以确保这些差异不会影响你的代码的语义。幸运的是,这种仔细的审查可以逐步向功能粒度进行。

this in function calls

在函数调用中f()this值是全局对象。在严格模式下,现在是undefined。当用callor 调用函数时apply,如果该值是原始值,则将该函数装入对象(或用于undefinedand 的全局对象null)中。在严格模式下,该值直接传递,无需转换或更换。

arguments 不会别名命名函数参数

在非严格模式下,修改arguments对象中的值会修改相应的命名参数。这使JavaScript引擎的优化变得复杂,并使代码更难阅读/理解。在严格模式下,arguments对象被创建并使用与命名参数相同的值进行初始化,但对arguments对象或命名参数的更改不会互相反映。

改成 eval

在严格的模式代码中,eval不会在调用它的作用域中创建新变量。另外,当然,在严格模式下,字符串将使用严格模式规则进行评估。需要进行彻底的测试以确保没有任何问题。如果你不需要它,不使用eval可能是另一个实用的解决方案。

Strictness-neutral code

将严格代码转换为严格模式的潜在“缺点”是在旧版浏览器中语义可能不同,这些浏览器不实现严格模式。在某些罕见的情况下(如错误连接或缩小),您的代码也可能无法在您编写和测试的模式下运行。以下是使代码严格中性的规则:

  1. 严格编写代码并确保没有严格的错误(从上面的“新运行时错误”部分)被抛出。
  2. 远离语义差异
    1. eval:只有当你知道你在做什么时才使用它
    2. arguments:始终通过名称访问函数参数,或者使用以下命令执行参数对象的副本: var args = Array.prototype.slice.call(arguments) 作为函数的第一行
    3. this:仅this在引用您创建的对象时使用。

Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.

JavaScript

JavaScript 是一种高级编程语言,通过解释执行,是一门动态类型,面向对象(基于原型)的解释型语言。它已经由ECMA(欧洲电脑制造商协会)通过 ECMAScript 实现语言的标准化。它被世界上的绝大多数网站所使用,也被世界主流浏览器( Chrome、IE、FireFox、Safari、Opera )支持。JavaScript 是一门基于原型、函数先行的语言,是一门多范式的语言,它支持面向对象编程,命令式编程,以及函数式编程。它提供语法来操控文本、数组、日期以及正则表达式等,不支持 I/O,比如网络