🔍JavaScript严格模式:你真的了解它的重要性吗?

前言

Hello~大家好。我是秋天的一阵风

对于很多初中级前端开发人员来说,严格模式 可能是一个相对陌生的概念。在当前的开发环境中,各种响应式框架层出不穷,如Vue、React、Angular等,这些框架极大地提高了开发效率,让开发者能够快速构建出功能强大的前端应用。然而,在这种快速开发的浪潮中,一些基础但重要的概念,比如严格模式,往往被开发者们忽略。

本文将从严格模式的基本概念出发,深入探讨严格模式在代码中的差异性。希望通过本文的介绍,能够帮助初中级前端开发者更好地理解严格模式,从而在日常开发中写出更规范、更可靠的代码。

一、什么是严格模式?

JavaScript严格模式是一种特殊的运行模式,它通过限制一些不规范的语法和行为,帮助开发者避免潜在的错误,提高代码的可维护性和稳定性。严格模式的主要好处包括:

  1. 防止意外全局变量的声明:在非严格模式下,未声明的变量可能会被自动提升为全局变量,这可能导致全局作用域的污染和难以追踪的错误。严格模式禁止了这种行为,确保所有变量都必须先声明再使用,从而避免了意外的全局变量声明。

  2. 增强代码的规范性 :严格模式禁止了一些不规范的语法和行为,如对undefinedInfinity等特殊值的赋值,以及使用with语句等。这些限制有助于开发者编写更规范、更清晰的代码,减少潜在的错误和问题。

  3. 提高代码的调试效率:严格模式会在一些可能导致错误的操作上抛出异常,而不是默默地忽略这些问题。这使得开发者能够在开发过程中更早地发现和修复错误,提高调试效率。

  4. 为未来的 ECMAScript 版本铺平道路 :未来版本的 ECMAScript 很有可能会引入新语法,ECMAScript5 中的严格模式就提早设置了一些限制来减轻之后版本改变产生的影响。如果提早使用了严格模式中的保护机制,那么做出改变就会变得更容易。

二、如何开启严格模式?

显示开启严格模式

1. 为脚本开启严格模式

'use strict' 放在所有语句之前

js 复制代码
// 整个脚本都开启严格模式的语法
"use strict";
const msg = "整个脚本都开启严格模式";

2. 为函数开启严格模式

'use strict' 放在函数体所有语句之前

js 复制代码
function myStrictFunction() {
  // 函数级别严格模式语法
  "use strict";
  function nested() {
    return "我也一样!";
  }
  return `你好!我是严格模式的函数!${nested()}`;
}
function myNotStrictFunction() {
  return "我不是严格模式的函数。";
}

隐式开启严格模式

在JavaScript中,除了显式地使用'use strict';声明来开启严格模式外,还有一些隐式的情况会自动启用严格模式。这些隐式严格模式主要出现在某些特定的上下文中,确保代码的执行符合严格模式的规则。

1. 模块环境(ES6模块)

在ES6模块中,所有代码默认运行在严格模式下。这意味着,如果你在使用importexport语法的模块中编写代码,这些代码会自动运行在严格模式下,而无需显式地添加'use strict';声明。

js 复制代码
// ES6模块
export function add(a, b) {
  return a + b;
}

2. 类的构造函数和方法

在ES6中,类的构造函数和方法也默认运行在严格模式下。这意味着,当你使用class语法定义类时,类中的所有方法和构造函数都会自动启用严格模式。

js 复制代码
class Person {
  constructor(name) {
    this.name = name;
  }

  greet() {
    console.log(`Hello, my name is ${this.name}`);
  }
}

3. 箭头函数

箭头函数在ES6中引入,它们默认运行在严格模式下。这意味着,当你使用箭头函数时,这些函数会自动启用严格模式,而无需显式地添加'use strict';声明。

js 复制代码
const add = (a, b) => {
  return a + b;
};

三、严格模式下的代码差异有哪些?

1. 变量操作的差异性

非严格模式

  • 使用前无需用var声明变量,未声明的变量会被自动提升为全局变量。
  • 可以直接对对象操作delete
  • 在正常模式下delete一个被var的变量,会失败(静默失败)且不会报错。
JavaScript 复制代码
// 非严格模式
a = 1; // 未声明直接赋值,a成为全局变量
console.log(Object.getOwnPropertyDescriptor(window, 'a'));
// {value: 1, writable: true, enumerable: true, configurable: true}
var a = 1;
console.log(Object.getOwnPropertyDescriptor(window, 'a'));
// {value: 1, writable: true, enumerable: true, configurable: false}
delete window.a; // 不报错,但delete失败
console.log(a); // 1

严格模式

  • 使用前必须用var声明变量,否则会抛出ReferenceError错误。
  • 不能直接对对象操作delete,会抛出TypeError错误。
  • 在严格模式下delete一个被var的变量,会变成报错。
JavaScript 复制代码
// 严格模式
'use strict';
var a = 1;
delete window.a; // 报错:Uncaught TypeError: Cannot delete property 'a' of [object Window]

2. 函数的this指向undefined

非严格模式

函数的this指向全局对象(在浏览器中是window)。

JavaScript 复制代码
// 非严格模式
function test() {
  console.log(this === window); // true
}
test();

严格模式

函数的this指向undefined

JavaScript 复制代码
// 严格模式
'use strict';
function test() {
  console.log(this === undefined); // true
}
test();

3. 禁止使用八进制

非严格模式

允许使用八进制表示。

JavaScript 复制代码
// 非严格模式
var value = 01010; // 八进制
console.log(value); // 520
严格模式

不允许使用八进制表示,会抛出SyntaxError错误。

JavaScript 复制代码
// 严格模式
'use strict';
var value = 01010; // 报错:Uncaught SyntaxError: Octal literals are not allowed in strict mode.

4. evalarguments不能作为标识符

非严格模式

可以使用evalarguments作为标识符。

JavaScript 复制代码
// 非严格模式
var eval = 1;
var arguments = 2;
console.log(eval); // 1
console.log(arguments); // 2

严格模式

使用evalarguments作为标识符会抛出SyntaxError错误。

JavaScript 复制代码
// 严格模式
'use strict';
var eval = 1; // 报错:Uncaught SyntaxError: Unexpected eval or arguments in strict mode
var arguments = 2; // 报错:Uncaught SyntaxError: Unexpected eval or arguments in strict mode

5. 不能使用with()

非严格模式

可以使用with()

JavaScript 复制代码
// 非严格模式
var obj = { a: 1 };
with (obj) {
  console.log(a); // 1
}

严格模式

使用with()会抛出SyntaxError错误。

JavaScript 复制代码
// 严格模式
'use strict';
var obj = { a: 1 };
with (obj) { // 报错:Uncaught SyntaxError: Strict mode code may not include a with statement
  console.log(a);
}

6. 不能使用arguments.calleecaller

非严格模式

可以使用arguments.calleecaller

JavaScript 复制代码
// 非严格模式
function test() {
  console.log(arguments.callee === test); // true
}
test();

function outer() {
  inner();
}
function inner() {
  console.log(inner.caller === outer); // true
}
outer();

严格模式

使用arguments.calleecaller会抛出TypeError错误。

JavaScript 复制代码
// 严格模式
'use strict';
function test() {
  console.log(arguments.callee === test); // 报错:Uncaught TypeError: 'callee' and 'caller' are restricted function properties and cannot be accessed in this context
}
test();


function outer() {
  inner();
}
function inner() {
  console.log(inner.caller === outer); // 报错:Uncaught TypeError: 'callee' and 'caller' are restricted function properties and cannot be accessed in this context
}
outer();

7. 实参和形参没有映射关系

非严格模式

通过arguments[0]修改实参,形参也会变化。

JavaScript 复制代码
// 非严格模式
function test(a) {
  arguments[0] = 20;
  console.log(a); // 20
}
test(10);

严格模式

修改arguments[0]不会影响形参。

JavaScript 复制代码
// 严格模式
'use strict';
function test(a) {
  arguments[0] = 20;
  console.log(a); // 10
}
test(10);

8. 参数是唯一的

非严格模式

函数参数可以是多个相同值且后面的会覆盖前面的值。

JavaScript 复制代码
// 非严格模式
function test(a, a) {
  console.log(a); // 20
}
test(10, 20);

严格模式

函数参数必须是唯一的,否则会抛出SyntaxError错误。

JavaScript 复制代码
// 严格模式
'use strict';
function test(a, a) { // 报错:Uncaught SyntaxError: Duplicate parameter name not allowed in this context
  console.log(a);
}
test(10, 20);

9. 对象操作的差异性

非严格模式

  • 对象可以有重名属性,后面的会覆盖前面的值。
  • 属性描述符出现不当操作的时候,会静默失败,不会报错。
JavaScript 复制代码
// 非严格模式
var obj = {
  name: 'owllai',
  name: 'owl'
};
console.log(obj); // { name: 'owl' }
Object.defineProperty(obj, 'name', {
  configurable: false
});
delete obj.name; // 不报错,但delete失败
console.log(obj); // { name: 'owl' }

严格模式

  • 对象不能有重名属性,否则会抛出SyntaxError错误。
  • 属性描述符出现不当操作的时候,会直接报错。
JavaScript 复制代码
// 严格模式
'use strict';
var obj = {
  name: 'owllai',
  name: 'owl' // 报错:Uncaught SyntaxError: Duplicate data property in object literal not allowed in strict mode
};
Object.defineProperty(obj, 'name', {
  configurable: false
});
delete obj.name; // 报错:Uncaught TypeError: Cannot delete property 'name' of #<Object>
相关推荐
钢铁男儿1 分钟前
Python内置类型子类化的陷阱与解决方案
开发语言·前端·python
野盒子11 分钟前
前端面试题 微信小程序兼容性问题与组件适配策略
前端·javascript·面试·微信小程序·小程序·cocoa
Hilaku19 分钟前
为什么我不再追流行,而是重新研究了 jQuery
前端·javascript·jquery
兔子1213520 分钟前
浏览器内容缓存数据量大时的优化方案
前端
G等你下课22 分钟前
JavaScript 中 Promise 的深度解析:异步编程的革新之路
前端·javascript
啃火龙果的兔子32 分钟前
安全有效的 C 盘清理方法
前端·css
海天胜景36 分钟前
vue3 数据过滤方法
前端·javascript·vue.js
天生我材必有用_吴用41 分钟前
深入理解JavaScript设计模式之策略模式
前端
海上彼尚43 分钟前
Vue3 PC端 UI组件库我更推荐Naive UI
前端·vue.js·ui
述雾学java43 分钟前
Vue 生命周期详解(重点:mounted)
前端·javascript·vue.js