知识问答

深入理解javascript严格模式

深入理解JavaScript严格模式

JavaScript严格模式(Strict Mode)是ECMAScript 5引入了一种新的执行模式,主要用于消除JavaScript语言的一些不合理、不严谨之处,减少一些怪异行为。

启用严格模式

全局启用严格模式

要想在全局范围启用严格模式,需要在JavaScript源码文件的顶部添加如下代码:

"use strict";

整个源码文件都会进入严格模式,包括该文件导入的所有模块也会进入严格模式。

局部启用严格模式

对于某个JS函数或某个代码块,也可以开启独立的严格模式。需要在函数或代码块的开头添加如下代码:

function strictModeExample1() {  "use strict";  // 代码块}
(function(){  "use strict";  // 代码块})();

严格模式带来的变化

1. 变量必须先声明,再使用

在非严格模式下,如果直接使用未经声明的变量,JavaScript会隐式地将其创建为一个全局变量,导致在某些情况下出现意外的变量名冲突。严格模式下,如果直接使用未经声明的变量,JavaScript直接抛出一个引用错误(ReferenceError)。

function strictModeExample2() {  "use strict";  var a = 1;  b = 2; // 直接使用未经声明的变量,在严格模式下,JavaScript抛出一个ReferenceError错误。  console.log(a, b);}strictModeExample2(); // 引用错误:b is not defined

2. 对象字面量中定义的重复属性会报错

在非严格模式下,如果一个对象字面量中定义了多个同名属性,则只会保留最后一个属性的值,其它属性都被忽略。在严格模式下,如果一个对象字面量中定义了多个同名属性,JavaScript会抛出一个语法错误(SyntaxError)。

function strictModeExample3() {  "use strict";  var data = {    name: 'Lucy',    email: 'lucy@example.com',    name: 'Lily' // 对象字面量中定义的重复属性,在严格模式下,JavaScript会抛出一个SyntaxError错误。  };  console.log(data);}strictModeExample3(); // 语法错误:Duplicate data property in object literal not allowed in strict mode

3. eval函数不会在其所在的作用域中作为本地变量绑定

非严格模式下,eval函数所执行的代码字符串中声明的变量会被添加到eval函数所在的作用域中。在严格模式下,eval函数不会在其所在的作用域中作为一个本地变量绑定,而是在一个新的、私有的作用域中执行,这意味着eval函数不能读写执行环境中的本地变量。

function strictModeExample4() {  "use strict";  eval('var foo = 1');  console.log(foo); // 严格模式下,变量foo不会添加到当前作用域中,JavaScript会抛出一个引用错误。}strictModeExample4(); // 引用错误:foo is not defined

4. 函数的参数名不能重复

在非严格模式下,如果两个参数的名称相同,JavaScript会默认忽略第二个参数的定义,这可能导致意料之外的行为。在严格模式下,如果两个参数名称相同,JavaScript会抛出一个语法错误(SyntaxError)。

function strictModeExample5(arg1, arg1) { // 在函数参数中定义的重复变量名称,在严格模式下,JavaScript会抛出一个SyntaxError错误。  "use strict";  console.log(arg1, arg1);}strictModeExample5(1, 2); // 语法错误:Duplicate parameter name not allowed in strict mode

5. 禁止this关键字指向全局对象

在非严格模式下,如果一个函数在全局上下文中调用,函数内部的this关键字会被绑定到全局对象上。在严格模式下,如果一个函数在全局上下文中调用,函数内部的this关键字会被绑定到undefined。

function strictModeExample6() {  "use strict";  console.log(this); // 在全局作用域中调用函数,严格模式下,函数内部的this关键字会被绑定到undefined。}strictModeExample6.call(null); // 输出:undefined

6. 运行eval或Function代码时,不会在其所在的外层作用域中创建新的变量或函数

在非严格模式下,eval或Function代码所在的作用域可以动态地创建新的变量或函数,这可能导致应用程序安全性方面的隐患。在严格模式下,eval或Function代码执行时,不会在其所在的外层作用域中创建新的变量或函数。

function strictModeExample7() {  "use strict";  var data = '0000';  eval('var data = "1111"');  console.log(data); // 在非严格模式下,data变量的作用域被改变,输出结果为1111。但在严格模式下,eval代码不会在其外层作用域中创建新的变量,输出结果仍为0000。}strictModeExample7(); // 输出:0000

示例

示例1:禁止使用with语句

严格模式下禁止使用with语句,因为该语句会增加程序的安全隐患,且容易出现引用错误。

function strictExample1() {  "use strict";  var myObject = {foo: 'bar'};  with(myObject) { // 严格模式下,使用with语句会抛出一个语法错误    console.log(foo);  }}strictExample1(); // 抛出语法错误:Strict mode code may not include a with statement

示例2:禁止在非函数代码块内声明函数

在非严格模式下,在if或for语句块中声明的函数会被提升到当前作用域的顶部,可能会覆盖同名的函数或变量。严格模式下,如果在非函数代码块内声明函数,JavaScript会抛出一个语法错误。

function strictExample2() {  "use strict";  if(true) {    function myFunction() { // 在严格模式下,函数不能在非函数代码快中定义。这里会抛出一个语法错误      console.log('Hello, Strict Mode!');    }    myFunction();  }}strictExample2(); // 抛出语法错误:In strict mode code, functions can only be declared at top level or inside a block.

结论

通过严格模式,JavaScript增加了许多新特性,去除了大量的不规范、不守规矩的操作,帮助开发者编写更加简洁、高效、可靠的代码。在能够掌握严格模式的基础上,开发者可以避免一些常见的JavaScript陷阱,提高代码的可读性和可维护性。