JavaScript 运行环境
JavaScript 运行时
Lynx 最大的特点之一是双线程架构(更多信息请参阅 ReactLynx 编程思想),JavaScript 代码会在主线程和后台线程两个线程上同时运行。两个线程使用了不同的 JavaScript 引擎作为其运行时。
主线程
Lynx 主线程负责处理直接影响屏幕像素渲染的任务,包括:执行主线程脚本、处理布局和渲染图形等等。
主线程使用由 Lynx 团队官方维护的 PrimJS 作为运行时,它是基于 QuickJS 的轻量、高性能 JavaScript 引擎,可以为主线程提供良好的运行性能。
后台线程
相对于主线程,Lynx 的后台线程处理的任务不直接影响屏幕像素的显示。这包括在后台运行的脚本和任务,它们与主线程分开运行。这样可以让主线程专注于处理用户交互和渲染,从而提升整体性能。
- Android:出于包体积和性能的综合考量,我们默认使用 PrimJS 作为运行时
- iOS:默认情况下使用 JavaScriptCore 作为运行时,但由于调试协议支持度的原因,当需要调试的时候,需要切换到 PrimJS。
虽然这些运行时引擎环境非常相似,但最终可能会遇到一些不一致的地方,请避免依赖任何运行时的具体细节。
JavaScript 语法转换
Lynx 双线程运行时支持最高的 ECMAScript 版本分别是:
当然,你可以使用新版本的 JavaScript 语法来编写代码,在构建时会使用 SWC 进行语法转换,而不需要等待 JavaScript 运行时支持。
JavaScript Polyfills
仅在 iOS 系统中注入 Polyfills
完整的 polyfill 列表见仓库除了对语法进行转换外,Lynx 还对很多内置的 API 提供了 polyfill,包括:
Built-in Objects
Array
- Array.prototype.concat
- Array.prototype.filter
- Array.prototype.flat
- Array.prototype.flatMap
- Array.prototype.includes
- Array.prototype[@@iterator]
- Array.prototype.map
- Array.prototype.reverse
- Array.prototype.slice
- Array.prototype.sort
- Array.prototype.species
- Array.prototype.splice
- Array.prototype[@@unscopables].flat
- Array.prototype[@@unscopables].flatMap
ArrayBuffer
Date
Number
Object
Promise
- Promise
- Promise.all
- Promise.race
- Promise.reject
- Promise.resolve
- Promise.prototype.catch
- Promise.prototype.finally
- Promise.prototype.then
Reflect
- Reflect.apply
- Reflect.construct
- Reflect.defineProperty
- Reflect.deleteProperty
- Reflect.get
- Reflect.getOwnPropertyDescriptors
- Reflect.getPrototypeOf
- Reflect.has
- Reflect.isExtensible
- Reflect.ownKeys
- Reflect.preventExtensions
- Reflect.set
- Reflect.setPrototypeOf
RegExp
- RegExp
- RegExp.prototype.exec
- RegExp.prototype.sticky
- RegExp.prototype.test
- RegExp.prototype.toString
String
- String.prototype.endsWith
- String.prototype.includes
- String.prototype.match
- String.prototype.matchAll
- String.prototype.padEnd
- String.prototype.padStart
- String.prototype.replace
- String.prototype.search
- String.prototype.split
- String.prototype.startsWith
- String.prototype.trim
- String.prototype.trimEnd
- String.prototype.trimStart
Symbol
- Symbol
- Symbol.prototype.description
- Symbol.asyncIterator
- Symbol.hasInstance
- Symbol.isConcatSpreadable
- Symbol.match
- Symbol.matchAll
- Symbol.replace
- Symbol.search
- Symbol.species
- Symbol.split
- Symbol.toPrimitive
- Symbol.toStringTag
模块系统
在开发 Lynx 项目时,开发者可封装和引用 JS 模块。
模块现在支持 ESModule 和 CommonJS 规范的模块系统。ESModule 和 CommonJS 可以混用。
推荐使用 ESModule,能够更好地进行 TreeShaking。
模块名
无论使用什么模块,都需要指定模块名。模块名可以是:
- 一个相对路径:
./common.js - 一个 npm 包名:
lodash(不支持依赖 C++ addon,不支持依赖 NodeJS 的内置库) - 经过 alias 处理的路径:
@common/foo.js
CommonJS
CommonJS 使用 require(path) 来引入一个模块。使用 module.exports 或 exports 来导出一个模块。
-
require可以出现在代码的任何位置,不需要在顶部。 -
require一个模块,会同步执行该模块内的代码。 -
require会缓存返回的对象,对同一路径多次require,会返回同一个对象。即:
ESModule
ESModule 使用 import 来引入一个模块。使用 export 来导出一个模块。
import 和 export 必须位于代码的最外层。
同时 ESModule 可以使用 import() 来进行动态导入模块。