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 代码戴上「严格模式」这副安全眼镜吧!

相关推荐
玖釉-3 分钟前
解决PowerShell执行策略导致的npm脚本无法运行问题
前端·npm·node.js
Larcher37 分钟前
新手也能学会,100行代码玩AI LOGO
前端·llm·html
徐子颐1 小时前
从 Vibe Coding 到 Agent Coding:Cursor 2.0 开启下一代 AI 开发范式
前端
小月鸭1 小时前
如何理解HTML语义化
前端·html
jump6801 小时前
url输入到网页展示会发生什么?
前端
诸葛韩信1 小时前
我们需要了解的Web Workers
前端
brzhang2 小时前
我觉得可以试试 TOON —— 一个为 LLM 而生的极致压缩数据格式
前端·后端·架构
yivifu2 小时前
JavaScript Selection API详解
java·前端·javascript
这儿有一堆花2 小时前
告别 Class 组件:拥抱 React Hooks 带来的函数式新范式
前端·javascript·react.js
十二春秋2 小时前
场景模拟:基础路由配置
前端