🔍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>
相关推荐
foxhuli2298 分钟前
禁止ifrmare标签上的文件,实现自动下载功能,并且隐藏工具栏
前端
青皮桔39 分钟前
CSS实现百分比水柱图
前端·css
失落的多巴胺39 分钟前
使用deepseek制作“喝什么奶茶”随机抽签小网页
javascript·css·css3·html5
DataGear42 分钟前
如何在DataGear 5.4.1 中快速制作SQL服务端分页的数据表格看板
javascript·数据库·sql·信息可视化·数据分析·echarts·数据可视化
影子信息44 分钟前
vue 前端动态导入文件 import.meta.glob
前端·javascript·vue.js
青阳流月1 小时前
1.vue权衡的艺术
前端·vue.js·开源
样子20181 小时前
Vue3 之dialog弹框简单制作
前端·javascript·vue.js·前端框架·ecmascript
kevin_水滴石穿1 小时前
Vue 中报错 TypeError: crypto$2.getRandomValues is not a function
前端·javascript·vue.js
翻滚吧键盘1 小时前
vue文本插值
javascript·vue.js·ecmascript
孤水寒月2 小时前
给自己网站增加一个免费的AI助手,纯HTML
前端·人工智能·html