是时候使用Javascript严格模式了

转载 2012年03月21日 13:12:29

 ECMAScript5将严格模式(strict mode)引入了Javascript中,目的是允许开发人员能够选择“更好”的Javascript版本,这个版本能用不同的方式处理那些普遍而又臭名昭著的错误。一开始的时候,我对该模式抱着怀疑的态度,因为当时在只有一款浏览器(Firefox)支持严格模式。时至今日,所有的主流浏览器的最新版本——包括IE10与Opera12——都支持严格模式。使用严格模式的时机已经成熟了。

  它带来了什么?

  严格模式给Javascript的运行方式带来了许多不同,我将它们分为了两类:明显的(obvious),以及微妙的(subtle)。那些微妙的改变是为了解决微妙的问题,我不打算在这里对其进行赘述。如果你对这些细节感兴趣,请参考Dmitry Soshnikov的精彩文章,《ECMA-262-5 in Detail. Chapter 2. Strict Mode》。我对介绍明显的变化更感兴趣:它们是你开始使用严格模式之前所必须了解的,也可能给你带来最多好处。

  在开始介绍特殊特性之前,你需要记住,严格模式的目标之一是允许更快地调试错误。帮助开发者调试的最佳途径是当确定的问题发生时抛出相应的错误(throw errors when certain patterns occur),而不是悄无声息地失败或者表现出奇怪的行为(这正是如今不在严格模式下的Javascript做的)。严格模式下的代码抛出更多的错误信息,这是好事,因为它能帮助开发者很快注意到一些必须立即解决的问题。

  去除with语句(Eliminates with)

  首先,严格模式去除了with语句。当with语句出现在严格模式中时,它会被认为是非法的Javascript语句并抛出语法错误。所以,使用严格模式的第一步就是确保你没有在使用with。
 // 在严格模式中将导致语法错误

  with (location) {

  alert(href);

  }

防止意外的全局变量(Prevents accidental globals)

  第二点是,变量在赋值之前必须声明。在非严格模式下,给一个未声明的变量赋值将自动生成一个该名字的全局变量。这是Javascript中最普遍的错误之一。严格模式中,这样做将抛出一个错误。
 // 严格模式中抛出一个错误

  (function() {

  someUndeclaredVar = "foo";

  }());


取消this值的强制转换(Eliminates this coercion)

  另一个重要的变化是,this值为null或undefined时,不会再将其强制转换为全局对象。也就是说,this保留了它的原始值,也因此可能会导致一些依赖于强制转换的代码发生错误。例如:

      window.color = "red";

  function sayColor() {

  // 严格模式下,this不会指向window

  alert(this.color);

  }

  // 以下两种情况,在严格模式下都抛出错误

  sayColor();

  sayColor.call(null);
根本而言,this值必须赋值,否则将保留undefined值。这意味着调用构造函数时若漏掉了new关键字也会导致错误:
function Person(name) {

  this.name = name;

  }

  // 严格模式下导致错误

  var me = Person("Nicholas");

在这段代码里,调用Person构造函数时缺少了new关键字,此时this值为undefined。由于你不能给undefined添加属性,这段代码抛出了一个错误。在非严格模式下,this会强制转换为全局对象,因此name属性能够被正确赋值为全局变量。

拒绝重复(No duplicates)
  当你做了大量的编码的时候,你很容易在对象中定义了重复的属性或者给函数定义了重复的参数名。严格模式下,这两种情况都会导致错误的发生:
  // 严格模式下错误 - 重复参数

  function doSomething(value1, value2, value1) {

  //code

  }

  // 严格模式下错误 - 重复属性

  var object = {

  foo: "bar",

  foo: "baz"

  };

  这两者都是语法错误,在代码执行之前将抛出错误。

更安全的eval()(Safer eval())
 eval()没有被移除,但它在严格模式下发生了一些变化。最大的改变是:在eval()语句中声明的变量以及函数不会在包含域中创建。例如:
 (function() {

  eval("var x = 10;");

  // 非严格模式下,x为10

  // 严格模式下,x没有声明,抛出一个错误

  alert(x);

  }());

 任意由eval()创建的变量或函数仍呆在eval()里。然而,你可以通过从eval()中返回一个值的方式实现值的传递:
 (function() {

  var result = eval("var x = 10, y = 20; x + y");

  // 严格模式与非严格模式下都能正常工作(得到30)

  alert(result);

  }());


不可改变引发的错误(Errors for immutables)
    ECMAScript 5 同时引入了修改属性特征的能力,例如设置一个属性为只读或者冻结整个对象的结构(freezing an entire object’s structure)。在非严格模式下,试图修改一个不可变的属性时将悄无声息地失败。你可能在使用一些原生APIs的时候已经遇到这类问题。严格模式将保证无论你在何时试图使用一种不被允许的方式修改一个对象或对象的属性时抛出错误。
      var person = {};

  Object.defineProperty(person, "name" {

  writable: false,

  value: "Nicholas"

  });

  // 非严格模式下将悄无声息地失败,严格模式则抛出错误

  person.name = "John";

 这个例子中,name属性被设置为只读。在非严格模式下,对name的赋值将悄无声息地失败;而在严格模式下,一个错误将被抛出。

  注:如果你在使用ECMAScript属性能力(the ECMAScript attribute capabilities),我强烈推荐你开启严格模式。如果你在改变对象的可变性(mutability of objects),你将遇到一堆错误,而它们在非严格模式下将被安静地带过。

该如何使用它?
  在现代浏览器中很容易启用严格模式,只需添加下面一条语句:

  "use strict";


  虽然这看起来只是一个没有赋值给变量的字符串,但它确实地指示了Javascript引擎切换为严格模式(那些不支持严格模式的浏览器只是简单地读取了这个字符串然后继续像平常一样运行)。你可以在全局或函数中使用它。话虽这么说,你永远不应该在全局中使用它。全局地使用这条指示,意味着同个文件下的所有代码都在严格模式下运行。

  // 别这么做

  "use strict";

  function doSomething() {

  // 这将在严格模式下运行

  }

  function doSomethingElse() {

  // 这也是

  }

  这看起来似乎不是个大问题,但在我们这个不同脚本堆积在一起的世界里(our world of aggressive script concatenation)将导致大麻烦。只要有一份脚本全局地包含这条指令,其它串联的脚本也将在严格模式下运行(可能引发一些你从没预想到的错误)。

  因此,最好只在函数内使用严格模式,例如:



  function doSomething() {

  "use strict";

  // 严格模式下运行

  }

  function doSomethingElse() {

  // 非严格模式下运行

  }



  如果你想讲严格模式应用于多个函数,可以使用如下模式( immediately-invoked function expression (IIFE)):

  (function() {

  "use strict";

  function doSomething() {

  // this runs in strict mode

  }

  function doSomethingElse() {

  // so does this

  }

  }());

  结论

  我强烈建议每一个人都开始使用严格模式。现在已经有足够多的浏览器支持该模式,它将把你从藏身代码的错误中拯救出来。你需要确保你没有全局地包含启用指令,但可以频繁地使用IIFEs给任意多的代码应用严格模式。一开始,你将碰到从没遇过的错误——这是很正常的。切换到严格模式后,你需要做足够多的测试来保证你已hold住你的代码。一定不能只是将“use strict”扔进你的代码然后就假设不会有错误发生。至少的至少,你该开始使用这个异常有用的语言特性来写更好的代码了.

是时候开始使用JavaScript严格模式了

ECMAScript5将严格模式(strict mode)引入了Javascript中,目的是允许开发人员能够选择“更好”的Javascript版本,这个版本能用不同的方式处理那些普遍而又臭名昭著的错...
  • offbye
  • offbye
  • 2014年07月29日 14:29
  • 959

Js中严格模式和非严格模式的区别

严格模式和非严格模式的区别 //f1.js 'use strice'; //整个js文件都是严格模式下执行的 var n = 1; var foo = function(){...}; //....
  • Ayiayi00
  • Ayiayi00
  • 2017年09月02日 18:17
  • 752

JavaScript严格模式与非严格模式之间的区别

严格模式 非严格模式 禁止使用with语句 允许使用with语句 所有变量要先声明 使用未声明的变量将隐式声明为全局变量 函数(非方法)中的this是und...
  • weixin_37986839
  • weixin_37986839
  • 2017年08月30日 00:45
  • 120

js中严格模式与普通模式区别

sunshinegirl 标签: js,javascript 1.不允许用with。 2.所有变量必须声明,赋值给未声明的变量报错,而不是隐匿创建全局变量。 3.eval中的代码不能创建eval...
  • sunshinegirl_7
  • sunshinegirl_7
  • 2015年10月30日 13:30
  • 1937

js中的 "use strict" 做了什么?使用严格模式有什么优点

标记 严格模式后 其一:如果在语法检测时发现语法问题,则整个代码块失效,并导致一个语法异常。 其二:如果在运行期出现了违反严格模式的代码,则抛出执行异常。 注:经过测试IE6,7,8,9均不支持...
  • lqr891109
  • lqr891109
  • 2016年06月06日 14:47
  • 232

原生JS(3)严格模式、变量声明、类型

(七)严格模式 ①ECMAScript5 引入了严格模式(strict mode)的概念。 严格模式是为JavaScript定义了一种不同的解析与执行模型,在这种模式下,ECMA3Script中的一些...
  • qq20004604
  • qq20004604
  • 2016年08月07日 03:27
  • 1478

js严格模式——arguments变为参数的静态副本

show u the code ! //一般模式 ! function (a){ arguments[0]=100; console.log(a);//undefined ...
  • yCharlee
  • yCharlee
  • 2016年09月05日 14:31
  • 872

ES6 严格模式

ES6 的模块自动采用严格模式,不管你有没有在模块头部加上"use strict";。 严格模式主要有以下限制。 变量必须声明后再使用函数的参数不能有同名属性,否则报错不能使用with语句...
  • fw19940314
  • fw19940314
  • 2017年10月23日 14:43
  • 339

visual studio code使用

ctrl+shift+P command palette ctrl+space 触发补全 ctrl+shift+F12 跳转 Ctrl+F12 ctrl+shift+M 查错 ctrl+s...
  • CSDNhuaong
  • CSDNhuaong
  • 2018年01月06日 21:23
  • 118

严格模式和非严格模式之间的区别

1、在严格模式中禁止使用with语句。 2、在严格模式中,所有的变量都要先声明,如果给一个未声明的变量、函数、函数参数、catch从句参数或全局对象的属性赋值,将会抛出一个引用错误(在非严格模式中,...
  • CatieCarter
  • CatieCarter
  • 2017年10月10日 15:20
  • 208
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:是时候使用Javascript严格模式了
举报原因:
原因补充:

(最多只允许输入30个字)