You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript调用提升函数时use strict未生效的原因

问题核心原因

这个现象的本质是你写的"use strict"根本没有生效,整个脚本全程运行在非严格模式(俗称"马虎模式/sloppy mode")下,和函数声明提升没有直接关系。


严格模式指令的生效规则

"use strict"从设计上就不是一个全局开关语句,而是一类特殊的「指令序言(Directive Prologue)」,ECMAScript规范对它的生效位置有非常严格的要求:

  • 它必须是所在作用域(脚本全局作用域/函数作用域)源码静态位置的最开头部分,前面只能有其他字符串形式的指令、或者代码注释,不能出现任何其他类型的实际语句。
  • 只要在"use strict"的源码前面出现了函数调用、变量声明、普通字面量表达式这类非指令语句,JS引擎在代码解析阶段就不会把它识别为严格模式开关,只会把它当成一个没有任何作用的普通字符串,直接忽略。

你写的第二份代码里,"use strict";的源码前一行就是myFunction();这个函数调用语句,从静态位置上就不符合指令序言的要求,所以从解析阶段开始,整个脚本就没有进入严格模式,严格模式的所有规则自然都不会生效。

注意:指令序言的判定是解析阶段基于源码的静态文本位置做的,和执行阶段的声明提升没有任何关系——哪怕函数声明会被提升到作用域顶部,只要源码里"use strict"前面有非指令语句,它就不会触发严格模式。


为什么没触发未声明变量报错

因为非严格模式下,JS对未声明变量的赋值行为有特殊的兼容逻辑:当你直接写x = 12而没有用var/let/const声明x时,引擎会沿着作用域链向上查找x的声明,如果一直找到全局作用域都没找到,不会抛错,反而会自动在全局对象上创建一个名为x的属性,也就是大家常说的「隐式全局变量」。
这也是为什么你写的x=12没有触发ReferenceError,脚本还能顺利执行到最后打印the script continues...——这本来就是非严格模式的默认行为。

你可以做个简单验证:把第二份代码里的"use strict"挪到脚本第一行(前面只留注释也可以),哪怕保留函数提前调用的写法,执行到x=12时照样会抛出你预期的未定义错误:

"use strict";
myFunction();
x = 12;
function myFunction() {

}
console.log('the script continues...') // 这行永远不会执行,因为前面已经抛错

为什么会影响全局作用域

就是上面提到的非严格模式隐式全局变量规则:你赋值的x没有任何块级/函数级的声明,最终会被直接挂载到全局对象(浏览器环境是window,Node.js环境是globalThis)上,成为全局可访问的属性。
这种隐式创建的全局变量很容易造成命名冲突、意外的值覆盖,也是严格模式专门要禁止这类写法的核心原因。


内容的提问来源于stack exchange,提问作者someusername12

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 18:31:13