当前位置: 首页 > news >正文

JavaScript 严格模式

如果你在 JavaScript 项目中见过代码顶部的'use strict',或许会疑惑:这行代码到底有什么用?为什么很多开发者会主动加上它?其实,这行代码开启的 “严格模式”,是 JavaScript 为提升代码质量、减少潜在 bug 而设计的重要特性。今天,我们就来深入聊聊严格模式 —— 它能解决什么问题、有哪些核心规则,以及如何在项目中正确使用。

一、为什么需要严格模式?先看两个 “坑”

在了解严格模式之前,我们先感受下 “非严格模式”(即普通模式)下的两个常见 “坑”,正是这些问题催生了严格模式的出现:

坑 1:意外创建全局变量

在普通模式下,如果不小心忘记用var/let/const声明变量,直接赋值(比如a = 10),JavaScript 会 “贴心” 地帮你创建一个全局变量。看似方便,实则隐藏巨大风险 —— 可能不小心覆盖全局对象上的原生属性(比如window上的方法),还会导致变量污染,后期难以定位问题:

// 普通模式:未声明变量赋值,自动成为全局变量function fn() {a = 10; // 相当于 window.a = 10(浏览器环境)}fn();console.log(a); // 10(意外泄露到全局)

坑 2:this自动绑定全局对象

普通模式下,函数中的this如果是null或undefined,会自动 “升级” 为全局对象(浏览器中是window,Node.js 中是global)。这会导致意外修改全局变量,比如:

// 普通模式:this意外绑定全局function printThis() {console.log(this === window); // true(本想this是null,结果变成window)this.name = "意外修改的全局变量";}printThis.call(null); // 手动传入nullconsole.log(window.name); // "意外修改的全局变量"(全局被污染)

这些 “宽松” 的规则,在早期帮新手降低了入门门槛,但也让代码充满隐患。而严格模式的核心作用,就是 “收紧” 这些规则 —— 把 “隐性错误” 变成 “显性报错”,强制开发者写出更规范的代码。

二、如何开启严格模式?两种方式

开启严格模式非常简单,只需在代码作用域的最顶部添加一行字符串'use strict'(单引号、双引号均可,甚至可以不加引号,但规范写法是带引号)。根据作用域不同,分为 “全局严格模式” 和 “局部严格模式”:

1. 全局严格模式:作用于整个脚本

在.js文件的第一行(或<script>标签内的第一行)添加'use strict',整个脚本都会处于严格模式下:

// 全局严格模式:作用于整个脚本'use strict';function fn() {a = 10; // 直接报错:ReferenceError(不再自动创建全局变量)}fn();

2. 局部严格模式:作用于单个函数

如果不想影响整个脚本(比如引入的第三方库不支持严格模式),可以只在特定函数内部开启严格模式,将'use strict'放在函数体的第一行:

// 普通模式:函数外不受影响function normalFn() {b = 20; // 普通模式:仍会创建全局变量}// 局部严格模式:仅strictFn内部生效function strictFn() {'use strict';c = 30; // 报错:ReferenceError}normalFn();console.log(b); // 20(全局变量)strictFn(); // 报错:c is not defined

最佳实践:推荐使用 “局部严格模式”(函数内开启),尤其是在多人协作或引入第三方代码的项目中,避免全局严格模式影响其他非严格代码。

三、严格模式的核心规则:7 个关键差异(附实例)

严格模式对 JavaScript 的语法和行为做了多处修改,我们挑最常用、影响最大的 7 个规则来详细说明,每个规则都对比 “普通模式” 和 “严格模式” 的差异:

1. 禁止未声明变量赋值:直接报错

这是严格模式最实用的规则之一。未用var/let/const声明的变量,赋值时不再创建全局变量,而是直接抛出ReferenceError,把 “隐性 bug” 提前暴露:

'use strict';function fn() {a = 10; // 报错:Uncaught ReferenceError: a is not defined}fn();

价值:强制开发者显式声明变量,从源头避免全局变量污染。

2. 禁止删除变量 / 函数:报错而非静默失败

普通模式下,用delete删除变量、函数或函数参数时,操作会 “静默失败”(返回false,但不报错,开发者可能误以为删除成功);严格模式下,这类操作会直接抛出SyntaxError:

'use strict';var num = 10;function fn() {}delete num; // 报错:Uncaught SyntaxError: Delete of an unqualified identifier in strict mode.delete fn; // 同样报错

注意:delete并非完全不能用 —— 删除对象的属性(比如delete obj.name)在严格模式下依然合法,只是禁止删除变量、函数等 “不可配置” 的对象。

3. 禁止函数参数重名:参数名必须唯一

普通模式下,函数参数允许重名(比如function fn(a, a){}),后一个参数会覆盖前一个,导致语义模糊;严格模式下,参数重名直接报错:

'use strict';// 报错:Uncaught SyntaxError: Duplicate parameter name not allowed in this contextfunction fn(a, a) {console.log(a); // 普通模式下会输出后一个a的值,严格模式直接不让定义}

价值:避免参数语义混淆,比如开发者可能误以为两个a是独立参数,实际后一个会覆盖前一个。

4. 八进制字面量必须用0o开头:禁止0开头

普通模式下,支持以0开头的八进制字面量(比如0123表示十进制的83),但这种写法容易与十进制数混淆(比如08本想表示 8,却因0开头变成无效八进制,普通模式下会解析为 8,逻辑矛盾);严格模式下,禁止0开头的八进制,必须用标准语法0o开头:

'use strict';console.log(0123); // 报错:Uncaught SyntaxError: Octal literals are not allowed in strict mode.console.log(0o123); // 83(正确写法,明确是八进制)

价值:统一数值表示方式,避免歧义,尤其是新手不会再因0开头的数字困惑。

5. 禁止使用with语句:提升性能与可读性

with语句的作用是 “临时将对象的属性纳入当前作用域”,比如with(obj){ console.log(name) },本意是简化属性访问,但会带来两个严重问题:

  • 无法确定name是obj.name还是全局变量,代码可读性差;
  • 干扰 JavaScript 引擎的优化,导致代码运行变慢。

因此,严格模式直接禁止with语句,使用即报错:

'use strict';var obj = { name: "Tom" };with(obj) { // 报错:Uncaught SyntaxError: Strict mode code may not include a with statementconsole.log(name);}// 替代方案:显式访问对象属性(更清晰)console.log(obj.name); // "Tom"

6. this不再自动绑定全局:保持原值

这是解决前文 “坑 2” 的关键规则。严格模式下,函数中的this会 “保持原值”—— 如果是null就还是null,是undefined就还是undefined,不再自动绑定到全局对象:

'use strict';function printThis() {console.log(this); // null(不再变成window)}printThis.call(null); // 手动传入null,this保持为null// 再比如:普通函数中的this(非箭头函数)function normalFunc() {console.log(this); // undefined(普通模式下是window)}normalFunc();

价值:避免this意外污染全局,让this的指向更可控(符合开发者预期)。

7. eval创建独立作用域:不污染外部

eval()函数用于执行字符串形式的代码,普通模式下,eval执行的代码会 “融入” 当前作用域,可能覆盖外部变量;严格模式下,eval会创建一个 “独立作用域”,执行的代码无法影响外部变量:

'use strict';var a = 10;// 严格模式:eval内部的变量不会污染外部eval('var a = 20; console.log(a);'); // 20(内部作用域的a)console.log(a); // 10(外部a不受影响)

补充:虽然严格模式让eval更安全,但仍不推荐频繁使用eval—— 它会降低代码可读性,还可能带来安全风险(比如执行用户输入的恶意代码)。

四、严格模式的实际应用场景:哪些项目需要用?

可能有人会问:现在都用 ES6 + 和现代框架了,还需要严格模式吗?答案是 “非常需要”,尤其是以下场景:

1. 所有生产环境项目:提前暴露 bug

无论是传统的 jQuery 项目,还是 Vue/React 项目(虽然框架内部已开启严格模式,但开发者写的业务代码仍可能有隐患),开启严格模式能在开发阶段就抛出潜在错误,避免上线后出现难以复现的 bug。比如:

  • 团队协作时,新人不小心写出未声明变量的代码,严格模式会直接报错,而不是让 bug 隐藏到线上;
  • 重构老代码时,严格模式能帮你发现隐藏的全局变量、不合理的this指向等问题。

2. 库 / 工具开发:避免影响外部环境

如果你开发的是供他人使用的库(比如封装的工具函数、组件库),必须开启严格模式。因为你无法确定使用者的项目是否是严格模式,严格模式能确保你的代码不会意外创建全局变量、污染外部this,避免给使用者带来麻烦。

3. 学习 JavaScript:理解语言本质

对于新手来说,严格模式能帮你更深刻理解 JavaScript 的语法规则。比如:

  • 为什么this有时是undefined?
  • 为什么变量必须声明后才能使用?

通过严格模式的报错信息,你能更快掌握 JavaScript 的 “边界”,避免被普通模式的 “宽松规则” 误导。

五、使用严格模式的注意事项:避免踩坑

虽然严格模式好处多多,但使用时也有几点需要注意,避免 “好心办坏事”:

1. 注意作用域边界:'use strict'必须在作用域顶部

严格模式的'use strict'必须放在作用域的 “最顶部”,如果前面有其他代码(除了注释),严格模式会失效。比如:

// 错误:'use strict'前有其他代码,严格模式失效var a = 10;'use strict';a = 20; // 普通模式:不会报错(因为严格模式没生效)正确写法是把'use strict'放在最前面(注释可以在前面):// 正确:注释后紧跟'use strict',严格模式生效/* 这是注释 */'use strict';var a = 10;a = 20; // 不报错(变量已声明)b = 30; // 报错:ReferenceError(变量未声明)

2. 兼容第三方库:避免全局严格模式冲突

如果你的项目中引入了老的第三方库(比如不支持严格模式的 jQuery 插件),不要在全局开启严格模式,否则可能导致库的代码报错。此时应使用 “局部严格模式”,只在自己写的函数内部开启严格模式,不影响第三方代码。

3. ES6 模块默认开启严格模式:无需手动加

需要注意的是,ES6 的模块(用import/export的文件)会默认开启严格模式,即使你不写'use strict',代码也会按照严格模式执行。比如:

// ES6模块文件(.mjs后缀或type="module"的<script>)// 无需写'use strict',默认是严格模式function fn() {a = 10; // 报错:ReferenceError}fn();

这也是为什么现代框架项目(比如 Vue CLI、Create React App 创建的项目)默认不用手动加'use strict'—— 因为项目已配置为 ES6 模块,严格模式已自动开启。

六、总结:严格模式不是 “束缚”,而是 “保护”

  • 减少隐性 bug:把未声明变量、不合理的this指向等隐性错误变成显性报错;
  • 提升代码质量:强制规范变量声明、参数命名、this指向等,让代码更易读、易维护;
  • 优化性能:禁止with语句等影响引擎优化的语法,让代码运行更快。
http://www.dtcms.com/a/430746.html

相关文章:

  • 数据时代的基石 —— 数据库的核心价值:MySQL 三大范式精讲
  • **跨平台开发:发散创新,探索无界限**随着技术的飞速发展,跨平台开发已经成为软件开发的必然趋势
  • 2025年中小工程企业成本管理新突破:如何选对管理软件?
  • JVM初始堆大小和最大堆大小多少合适?
  • 网站汉英结合的怎么做织梦欧美网站模板
  • 构建AI智能体:五十、ModelScope MCP广场 · MCP协议 · Cherry Studio:AI应用生产线
  • 从零开始:MCP数据库助手(二)- 核心功能实现
  • Django Admin 完全指南:内置功能、高级使用与第三方扩展
  • Django 路由详解
  • Django Admin 配置完全指南:从基础到高级实战
  • MySQL 全量 + 增量备份脚本(RPM 安装)实践与问题解析
  • 嘉兴网站建设方案外包运营推广公司
  • 第6章串数组:稀疏矩阵三元组顺序表的行逻辑连接顺序表
  • MATLAB仿真:编程基础实验全解析——从入门到实战
  • [特殊字符]灵感补给站 | pinterest 设计灵感分享 UI版面设计2
  • seo与网站建设php网站开发文档模板
  • GameObject 常见类型详解 -- 任务给予对象(QUESTGIVER)
  • docker部署mssql
  • 网站备案能查到什么wordpress关键字设置
  • LAMA(2014): 一项对SCADE模型进行基于SMT验证的开源方案
  • 从AGI到ASI演化的路径与启示
  • 重庆孝爱之家网站建设邢台是哪个省的城市
  • 【Linux学习笔记】线程概念和控制(二)
  • AES-128 CMAC:保障嵌入式通信安全的认证算法
  • Oumi:开源的AI模型一站式开发平台,涵盖训练、评估和部署模型
  • 大数据消息中间件选型终极指南:深度解析Kafka、Pulsar、RocketMQ架构与性能
  • 网站推广排名收费南昌做企业网站
  • 【Mosquitto的数据流程架构】
  • 新手学网站建设视频教程共30课高清版做网站需要编程
  • Kubernetes实战:MariaDB误删恢复与数据持久化