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










使用不当的问题由于子模块先于父模块被执行,子模块直接执行从父模块导入的变量会导致 JS 错误 。
// 文件 parent.jsimport {} from './child.js';export const parent = 'parent';// 文件 child.jsimport { parent } from './parent.js';console.log(parent); // 报错代码 2如代码 2 所示,child.js 中的导入变量 parent 被绑定为 parent.js 的导出变量 parent,当执行 child.js 的最后一行代码时,parent.js 还没有被执行,parent.js 的导出变量 parent 未被初始化,所以 child.js 中的导入变量 parent 也就没有被初始化,会导致 JS 错误 。注意,本文说的变量是统称,包含 var、let、const、function 等关键字声明的变量 。
console.log(parent)^ReferenceError: Cannot access 'parent' before initialization如果是异步执行,则没问题,因为异步执行的时候父模块已经被执行了 。例如,代码 3 是能正常运行的 。// parent.jsimport {} from './child.js';export const parent = 'parent';// child.jsimport { parent } from './parent.js';setTimeout(() => {console.log(parent) // 输出 'parent'}, 0);代码 3纠正教程观点《ECMAScript 6 入门教程》一书说的三个重大差异如下:
- CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用 。
- CommonJS 模块是运行时加载,ES6 模块是编译时输出接口 。
- CommonJS 模块的 require() 是同步加载模块,ES6 模块的 import 命令是异步加载,有一个独立的模块依赖的解析阶段 。
分析问题对 JS 模块机制有了更深刻的理解后,我们回来分析我遇到的问题 。
问题一首先分析图 1 的报错 。业务方 App 的工程代码用 webpack 打包,所以实际运行的是 CommonJS 模块 。上面讲过 CommonJS 模块循环引用使用不当一般不会导致 JS 错误,为啥这里会出现 JS 报错呢?这是因为,循环引用使用不当导致变量的值为 undefined,我们的代码使用了 extends[21],而 extends 不支持 undefined 。由于使用了 Bable[22] 进行转码,所以由垫片 _inherits[23] 报错 。另外一个典型的不支持的 undefined 的 case 是 Object.create(undefined) 。
推荐阅读
- 课税对象是指哪些
- 已婚女人梦见找对象是什么意思
- 梦见对象出轨是什么意思
- 作和做的区别
- 快手怎么给对象评论
- 水鸡命找什么对象
- 任意与随意的区别
- 与发展对象关系怎么填写
- 小说剑来有几个对象
- 梦见对象出轨什么征兆
