JS 严格模式:从「自由散漫」到「规范严谨」的代码指南

JS 严格模式:从「自由散漫」到「规范严谨」的代码指南

在 JavaScript 世界里,「普通模式」像无人看管的菜市场------允许未声明变量、容忍重复参数、this 指向飘忽不定;而「严格模式」则像有规可循的写字楼,用明确规则规避潜在风险、提升代码质量。作为现代前端开发的标配,严格模式不仅是 ES5 引入的重要特性,更是 webpack 等构建工具的默认配置。今天,我们就从「是什么、做什么、为什么用、怎么用」四个维度,彻底搞懂 JS 严格模式。

一、先搞懂:严格模式到底是什么?

严格模式("use strict")是 JavaScript 的一种限制性执行模式 ,从 ECMAScript 5 开始引入。它的核心目标是:修复语言设计缺陷、禁止不安全操作、规范代码行为,让 JS 代码从「灵活但混乱」走向「严谨且可控」。

可以用一个生动的类比理解两种模式的差异:

  • 普通模式:在家办公,穿着睡衣也能写代码,偶尔偷懒(比如不声明变量)也没人管;
  • 严格模式:去公司上班,必须遵守规章制度(变量要声明、参数不重复),每一步操作都有明确规范。

启用方式也很简单,只需在代码最顶部(或函数内部顶部)添加一行字符串:

js 复制代码
// 全局启用严格模式(整个脚本文件生效)
"use strict";

// 或在函数内部启用(仅该函数生效)
function strictFunc() {
  "use strict";
  // 函数内代码遵循严格模式
}

特别注意:ES 模块(使用 import/export 的文件)会默认启用严格模式 ,无需手动添加 "use strict"

二、核心重点:严格模式到底限制了什么?

严格模式的核心价值,在于通过「禁止错误操作」提前暴露问题。下面我们逐一拆解它的关键限制,结合代码对比理解差异。

1. 禁止使用「未声明的变量」:杜绝全局污染

这是严格模式最常用的限制之一。在普通模式下,未声明的变量会自动成为全局变量(浏览器中挂载到 window),很容易意外覆盖全局属性;而严格模式会直接报错,从源头避免全局污染。

模式 代码示例 执行结果
普通模式 a = 10; console.log(window.a); 不报错,输出 10(变量自动挂载到 window
严格模式 "use strict"; a = 10; 直接抛出 ReferenceError: a is not defined

生活类比:就像你不能随便占用公司公共工位放私人物品------使用变量前,必须先「声明」(申请使用权)。

2. 改变 this 指向规则:告别「飘忽不定」

this 指向是 JS 初学者的高频痛点,普通模式下「直接调用的函数中,this 指向全局对象」的设计,更是坑了无数开发者。而严格模式通过固定 this 指向逻辑,彻底解决了这个问题。

我们用「对象方法内部函数」的经典场景对比:

场景 1:全局函数中的 this
js 复制代码
// 普通模式:this 指向 window(浏览器)
function nonStrictThis() {
  console.log(this === window); // 输出 true
}
nonStrictThis();

// 严格模式:this 指向 undefined
"use strict";
function strictThis() {
  console.log(this === undefined); // 输出 true
}
strictThis();
场景 2:对象方法的内部函数
js 复制代码
const obj = {
  name: "Alice",
  greet: function () {
    console.log("Hello " + this.name); // 这里 this 指向 obj(两种模式一致)
    
    // 内部函数的 this 差异
    function innerFunc() {
      console.log("Inner this:", this);
    }
    innerFunc();
  }
};

// 普通模式:innerFunc 中 this 指向 window(意外全局污染风险)
obj.greet(); // Inner this: Window

// 严格模式:innerFunc 中 this 指向 undefined(明确且安全)
"use strict";
obj.greet(); // Inner this: undefined

关键结论 :严格模式下,「直接调用的函数」(非对象方法、非 new 构造、非 bind/call/apply 绑定)中,this 固定为 undefined,不再默认指向全局对象。

如果想让内部函数的 this 指向外部对象(比如 obj),有三种常用解决方案:

  1. 用箭头函数 :自动捕获外部作用域的 this

    js 复制代码
    const innerFunc = () => {
      console.log(this); // 指向 obj
    };
  2. 保存外部 this 到变量 (经典 self 技巧)

    js 复制代码
    const self = this; // 保存 obj 到 self
    function innerFunc() {
      console.log(self); // 指向 obj
    }
  3. bind 绑定 this

    js 复制代码
    const boundFunc = innerFunc.bind(this);
    boundFunc(); // 指向 obj

3. 禁止删除变量/函数:避免误操作

普通模式下,删除变量、函数或函数参数不会报错(但实际也删不掉);严格模式下,这类操作会直接抛出语法错误,避免「误删关键资源」。

js 复制代码
// 普通模式:删除变量不报错,但无效
var b = 20;
delete b; // 返回 false(删除失败)
console.log(b); // 仍输出 20

// 严格模式:删除变量直接报错
"use strict";
var b = 20;
delete b; // SyntaxError: Delete of an unqualified identifier in strict mode

同样,删除函数、函数参数也会报错:

js 复制代码
"use strict";
function sayHello() {}
delete sayHello; // 报错

function func(x) {
  delete x; // 报错
}

4. 禁止函数参数重名:杜绝参数覆盖

普通模式下,允许函数参数重名,后面的参数会覆盖前面的参数(比如 function func(x, x) {});严格模式下,参数重名直接报错,避免「参数值被意外覆盖」的隐蔽 bug。

js 复制代码
// 普通模式:参数重名不报错,后值覆盖前值
function duplicateParams(x, x) {
  console.log(x); // 输出 2(第二个 x 覆盖第一个)
}
duplicateParams(1, 2);

// 严格模式:参数重名直接报错
"use strict";
function duplicateParams(x, x) {} 
// SyntaxError: Duplicate parameter name not allowed in this context

5. 禁止八进制字面量:统一数字语法

普通模式下,以 0 开头的数字会被解析为八进制(比如 0123 等于十进制 83);但这种语法不直观,且容易和十进制数字混淆。严格模式禁止这种写法,推荐用 0o 前缀表示八进制(更规范)。

js 复制代码
// 普通模式:0123 被解析为八进制
var octalOld = 0123;
console.log(octalOld); // 输出 83

// 严格模式:0123 报错,0o123 合法
"use strict";
var octalOld = 0123; // SyntaxError: Octal literals are not allowed in strict mode
var octalNew = 0o123; // 合法,输出 83

6. 其他重要限制:细节处规避风险

除了上述核心限制,严格模式还有几个实用规则:

  • 禁止 with 语句with 会动态改变作用域链,导致代码难以理解和优化,严格模式直接禁用;

    js 复制代码
    "use strict";
    const obj = { prop: 1 };
    with (obj) { prop = 2; } // SyntaxError: Strict mode code may not include a with statement
  • 禁止在代码块中声明函数iffor 等代码块中声明函数会报错(避免作用域混乱);

  • eval() 更安全eval 内创建的变量不会污染外部作用域(比如 eval("var a = 10") 后,外部无法访问 a);

  • 禁止修改只读属性 :尝试修改对象的只读属性(比如 Object.freeze(obj) 后的对象)会报错,而非静默失败。

三、为什么必须用严格模式?

很多开发者觉得「严格模式限制太多,没必要用」,但实际上,它的好处远大于「不便」:

  1. 提前暴露 bug:未声明变量、参数重名等问题,在普通模式下可能隐藏很久,严格模式会直接报错,帮你在开发阶段解决问题;
  2. 减少全局污染 :禁止未声明变量自动成为全局变量,避免意外覆盖 window 上的原生属性(比如 window.alert);
  3. 提升代码性能 :严格模式下,JS 引擎无需处理「自动绑定全局 this」「动态作用域链(with)」等复杂逻辑,可以更好地优化代码;
  4. 适配现代 JS:ES6+ 特性(如箭头函数、模块)的设计都基于严格模式,不用严格模式会导致部分新特性无法正常工作;
  5. 工具默认支持:webpack、Vite 等构建工具会自动在打包后的代码中添加严格模式,与其被动接受,不如主动适配。

四、实际开发中的最佳实践

掌握严格模式的「用法技巧」,才能真正发挥它的价值:

1. 启用方式:全局 vs 局部

  • 全局启用 :在脚本文件最顶部添加 "use strict"(适合独立 JS 文件);
  • 局部启用:在函数内部顶部添加(适合老项目迁移,避免全局影响其他非严格模式代码);
  • ES 模块无需手动加 :使用 import/export 的文件默认启用严格模式。

2. webpack 中如何控制严格模式?

webpack 会默认在打包后的代码中添加严格模式,如果确实需要禁用(不推荐),可以通过 TerserPlugin 配置:

js 复制代码
// webpack.config.js
const TerserPlugin = require("terser-webpack-plugin");

module.exports = {
  optimization: {
    minimizer: [
      new TerserPlugin({
        terserOptions: {
          compress: {
            strict: false, // 禁用严格模式
          },
        },
      }),
    ],
  },
};

3. 开发工具辅助:提前发现问题

在 VS Code 等 IDE 中,开启「严格模式检查」:

  • 安装 ESLint 插件,配置 eslint:recommended 规则(默认包含严格模式检查);
  • 编写代码时,未声明变量、参数重名等问题会实时标红,无需等到运行时才发现。

五、记忆口诀:30 秒记住核心规则

为了方便记忆,我们总结一句口诀,涵盖严格模式的核心限制:

javascript 复制代码
未声明变量不能用,删除变量行不通;
this 指向要明确,参数不能重复用;
八进制数弃旧法,with 语句全禁用;
eval 不污染作用域,只读属性别改动。

六、总结:严格模式是代码的「安全气囊」

如果把 JS 代码比作一辆车,普通模式就像没有安全气囊的旧车------看似灵活,实则风险重重;而严格模式则是现代汽车的「安全气囊+安全带」,用规则守护代码安全,用规范提升开发效率。

在现代前端开发中,严格模式早已不是「可选配置」,而是「标配要求」。无论是自己写代码,还是维护老项目,都建议主动启用严格模式------它或许会让你在写代码时多花一点时间规范语法,但能帮你避免无数个线上隐蔽 bug。

从今天开始,给你的 JS 代码戴上「严格模式」这副安全眼镜吧!

相关推荐
Hy行者勇哥21 小时前
前端代码结构详解
前端
代码AI弗森21 小时前
使用 JavaScript 构建 RAG(检索增强生成)库:原理与实现
开发语言·javascript·ecmascript
Lhy@@21 小时前
Axios 整理常用形式及涉及的参数
javascript
练习时长一年21 小时前
Spring代理的特点
java·前端·spring
水星记_21 小时前
时间轴组件开发:实现灵活的时间范围选择
前端·vue
2501_930124701 天前
Linux之Shell编程(三)流程控制
linux·前端·chrome
潘小安1 天前
『译』React useEffect:早知道这些调试技巧就好了
前端·react.js·面试
@大迁世界1 天前
告别 React 中丑陋的导入路径,借助 Vite 的魔法
前端·javascript·react.js·前端框架·ecmascript
EndingCoder1 天前
Electron Fiddle:快速实验与原型开发
前端·javascript·electron·前端框架
EndingCoder1 天前
Electron 进程模型:主进程与渲染进程详解
前端·javascript·electron·前端框架