js在for循环中使用java代码 javascript遍历对象

背景大力教育的在线教室中台提供封装了核心能力的教室 SDK,业务方基于教室 SDK 开发面向用户的在线教室 App 。最近对教室 SDK 做一次比较大的改动时,我遇到了一个懵逼的问题 。这个问题耗费了我 3 天左右时间,让我压力一度大到全身发热 。当时虽然解决了问题,但并没有很理解原因 。直到一个多月后,才有时间做一些更深入的分析,并写下这篇文章 。
当时的情况是,业务方 App 工程能通过 TypeScript 编译,但在运行时会报错 。就不同的使用教室 SDK 的方式,报错有两种 。图 1 为在业务方 App 工程里正常安装教室 SDK 后进行调试时的报错;图 2 为在业务方 App 工程里 yarn link 教室 SDK 后进行调试时的报错 。

js在for循环中使用java代码 javascript遍历对象

文章插图

js在for循环中使用java代码 javascript遍历对象

文章插图
在分析这个问题前,需要先分析一下 JS(JavaScript)的模块机制 。
CommonJS vs ES6 模块CommonJS 与 ES6(ECMAScript 6)模块有什么区别呢?《ECMAScript 6 入门教程 》[1]一书在“Module 的加载实现”章节指出两个模块体系有三个重大差异 。个人觉得这三个差异基本是错误的,给大家造成了不少误解 。后面再讲质疑的理由,这里先抛出我总结的几点差异:
CommonJS 模块由 JS 运行时实现,ES6 模块借助 JS 引擎实现;ES6 模块是语言层面的底层的实现,CommonJS 模块是之前缺失底层模块机制时在上层做的弥补 。从报错信息可以察觉这个差异 。CommonJS 模块同步加载并执行模块文件,ES6 模块提前加载并执行模块文件 。CommonJS 模块在执行阶段分析模块依赖,采用深度优先遍历(depth-first traversal),执行顺序是父 -> 子 -> 父;ES6 模块在预处理阶段分析模块依赖,在执行阶段执行模块,两个阶段都采用深度优先遍历,执行顺序是子 -> 父 。CommonJS 模块循环引用使用不当一般不会导致 JS 错误;ES6 模块循环引用使用不当一般会导致 JS 错误 。CommonJS 模块的导入导出语句的位置会影响模块代码执行结果;ES6 模块的导入导出语句位置不影响模块代码语句执行结果 。为了方便说明,本文把 JS 代码的运行大致分为预处理和执行两个阶段,注意,官方并没有这种说法 。下面进行更细致的分析 。
CommonJS 模块在 Node.js 中,CommonJS 模块[2]由 cjs/loader.js[3] 实现加载逻辑 。其中,模块包装器是一个比较巧妙的设计 。
在浏览器中,CommonJS 模块一般由包管理器提供的运行时实现,整体逻辑和 Node.js 的模块运行时类似,也使用了模块包装器 。以下分析都以 Node.js 为例 。
模块使用报错CommonJS 模块使用不当时,由 cjs/loader.js 抛出错误 。比如:
// Node.js internal/modules/cjs/loader.js:905 throw err; ^ Error: Cannot find module './none_existed.js' Require stack: - /Users/wuliang/Documents/code/demo_module/index.js可以看到,错误是通过 throw 语句抛出的 。
模块执行顺序CommonJS 模块是顺序执行的,遇到 require 时,加载并执行对应模块的代码,然后再回来执行当前模块的代码 。
如图 3 所示,模块 A 依赖模块 B 和 C,模块 A 被 2 个 require 语句从上往下分为 3 段,记为 A1、A2、A3 。
js在for循环中使用java代码 javascript遍历对象

文章插图
如图 4 所示,代码块执行顺序为:A1 -> B -> A2 -> C -> A3 。
js在for循环中使用java代码 javascript遍历对象

文章插图
模块循环引用从 cjs/loader.js 的 L765、L772 和 L784 行代码可以看到,在模块执行前就会创建好对应的模块对象,并进行缓存 。模块执行的过程实际是在给该模块对象计算需要导出的变量属性 。因此,CommonJS 模块在启动执行时,就已经处于可以被获取的状态,这个特点可以很好地解决模块循环引用的问题 。


以上关于本文的内容,仅作参考!温馨提示:如遇健康、疾病相关的问题,请您及时就医或请专业人士给予相关指导!

「四川龙网」www.sichuanlong.com小编还为您精选了以下内容,希望对您有所帮助: