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

JavaScript 立即执行函数(IIFE)运行时行为分析笔记

一、代码示例

(function() {// IIFE 函数作用域console.log(typeof foo); // 第一次打印console.log(typeof bar); // 第二次打印function foo() {} // 函数声明var bar = 10;    // 变量声明console.log(typeof foo); // 第三次打印console.log(typeof bar); // 第四次打印
})();

二、作用域结构分析

IIFE 形成了嵌套的作用域结构,决定了变量的可见性:

  • 全局作用域:包含 IIFE 函数本身(IIFE 作为全局作用域的一个函数)。
  • IIFE 函数作用域:嵌套在全局作用域内,包含 foo(函数)和 bar(变量)的声明,是本次分析的核心作用域。

三、变量提升(Hoisting)机制

JavaScript 引擎在编译阶段会将声明(函数声明、变量声明)提升到当前作用域顶部,赋值操作保留在原地,代码实际执行顺序如下:

(function() {// 编译阶段提升的内容:function foo() {}  // 函数声明整体提升(含函数体)var bar;          // 变量声明提升(初始值为 undefined)// 执行阶段:按顺序执行console.log(typeof foo); // 第一次打印console.log(typeof bar); // 第二次打印bar = 10;         // 变量赋值(保留在原位置)console.log(typeof foo); // 第三次打印console.log(typeof bar); // 第四次打印
})();
  • 函数声明提升:函数声明(function foo() {})会被完整提升到作用域顶部,在声明前即可访问。
  • var 声明提升var 声明的变量(var bar = 10)仅提升声明部分,赋值操作留在原地,声明前访问时默认值为 undefined

四、执行上下文生命周期

执行上下文是函数运行时的环境,其生命周期分为创建阶段(编译时)和执行阶段(运行时)。

1. 创建阶段(编译时)

此阶段为执行做准备,确定变量存储、作用域链和 this 指向:

  • 变量对象(Variable Object,VO):存储当前作用域内的声明(函数/变量)
VO = {foo: function() {},  // 函数声明整体提升bar: undefined       // var 变量声明提升,初始值为 undefined
}
  • 作用域链:由内到外依次关联嵌套的作用域,此处为 [IIFE 函数作用域, 全局作用域]
  • this 指向:非严格模式下指向全局对象(浏览器中为 window

2. 执行阶段(运行时)

按代码顺序执行,修改变量对象中的值:

  • 执行赋值操作(bar = 10),变量对象更新为:
VO = {foo: function() {},  // 函数声明保持不变bar: 10              // 变量赋值后的值
}
  • 按顺序执行代码,完成打印等操作。

五、四次打印结果详解

打印位置变量输出结果原因解释
第一次typeof foo"function"函数声明被提升到作用域顶部,声明前可直接访问(函数类型)
第二次typeof bar"undefined"bar 仅提升声明,未执行赋值,默认值为 undefined(undefined 类型)
第三次typeof foo"function"函数声明未被修改,仍为函数类型
第四次typeof bar"number"bar 已执行赋值(bar = 10),类型为数字(number 类型)

六、编译阶段与运行阶段的核心差异

JavaScript 引擎对代码的处理分为两个明确阶段,是理解变量提升、作用域等机制的关键:

阶段时间点核心工作影响范围
编译阶段代码执行前1. 解析代码结构,确定作用域嵌套关系; 2. 处理声明提升(函数声明整体提升,var 声明仅提升名称)作用域结构、变量归属
运行阶段代码执行时1. 创建执行上下文(变量对象、作用域链、this 指向); 2. 逐行执行代码,修改变量值变量实际值、this 指向、运行状态

七、关键知识点补充

  1. 函数声明与变量声明的优先级
    同作用域内若存在同名函数声明和变量声明,函数声明会覆盖变量声明(但变量赋值会覆盖函数声明)。
    示例:
(function() {var foo = 'bar'; console.log(foo); // 输出 "bar"(变量赋值覆盖函数声明)function foo() {} 
})();
  1. var 与 let/const 的差异
    let/const 声明的变量存在“暂时性死区(TDZ)”,声明前访问会报错(ReferenceError),而 var 声明无此限制。
    示例:
(function() {console.log(bar); // 报错:ReferenceError(处于 TDZ)let bar = 10;
})();
  1. 作用域与执行上下文的关系
    作用域是静态结构(定义时确定),决定变量可见范围;执行上下文是动态状态(运行时创建),存储变量实际值,二者通过作用域链关联。

通过以上分析,可清晰理解 IIFE 运行时的变量提升、作用域交互及执行上下文变化,进而掌握 JavaScript 核心运行机制。

http://www.lryc.cn/news/600996.html

相关文章:

  • golang实现一个规则引擎,功能包括实时增加、修改、删除规则
  • GO 从入门到精通2
  • 什么是缓存雪崩?缓存击穿?缓存穿透?分别如何解决?什么是缓存预热?
  • 编程语言Java——核心技术篇(四)集合类详解
  • 【Pandas】pandas Index objects Index.shape
  • 【595驱动8*8点阵】2022-9-11
  • Linux文件系统管理——NFS服务端的安装配置与NFS客户端的安装与挂载实操教程
  • QT核心————信号槽
  • MyBatis-Plus 进阶功能:分页插件与乐观锁的实战指南
  • org.apache.lucene.search.Query#rewrite(IndexSearcher)过时讲解
  • 框架式3D打印机结构设计cad【9张】三维图+设计说明书
  • Windows Server存储池,虚拟磁盘在系统启动后不自动连接需要手动连接
  • vulhub Earth靶场攻略
  • Java:采用mybatis+pagehealper优雅的实现分页功能
  • 文件操作认识
  • connect系统调用及示例
  • 使用Python实现单词记忆软件
  • 零基础学习性能测试第三章:jmeter性能组件应用(事件,并发,定时器)
  • 大模型 vs 轻量模型:架构与使用场景对比
  • 单片机ADC机理层面详细分析(一)
  • nfls dp 刷题 题解
  • C++平衡二叉搜索树易错点
  • C++ 类型萃取:深入理解与实践
  • git推送文件失败
  • vulhub-earth靶机攻略
  • 显式等待和隐式等待的区别
  • 伟淼科技李志伟:破解二代接班传承困局,系统性方案破除三代魔咒
  • pytorch学习笔记-自定义卷积
  • Bert项目--新闻标题文本分类
  • C# 位运算及应用