ArkTS高性能编程最佳实践
ArkTS作为鸿蒙应用开发主力语言,高性能编程直接影响用户体验(流畅度、响应速度)与设备资源利用(内存、CPU)。
优化后应用启动速度提升,UI渲染帧率提升,内存占用减少。
-
const声明不变变量
不变的变量推荐使用const声明。const index = 10000; // 该 变 量 在 后 续 过 程 中 未 发 生 改 变 , 建 议 声 明 成 常 量 -
避免数值类型混用
引擎类型动态切换会导致性能损耗。let intNum = 1; intNum = 1.1; // 该 变 量 在 声 明 时 为 整 型 数 据 , 建 议 后 续 不 要 赋 值 浮 点 型数 据 let doubleNum = 1.1; doubleNum = 1; // 该 变 量 在 声 明 时 为 浮 点 型 数 据 , 建 议 后 续 不要 赋 值 整 型 数据 -
循环常量提取
原理:减少循环体内重复访问对象属性、数组元素或调用方法的开销,将不变的引用提取到循环外部。
优化前(性能较差)class Time { static start: number = 0; static info: number[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; } function getNum(num: number): number { let total: number = 348; for (let index: number = 0x8000; index > 0x8; index >>= 1) { / / 多 次 对 T ime 的 in f o 及 s t a r t 进 行 查 找 , 并 且 每 次 查找 出 来 的 值 是相 同 的 total += ((Time.info[num - Time.start] & index) !== 0) ? 1 : 0; } return total; }可以将Time.info[num - Time.start]提取为常量,这样可以显著减少属性访问次数,提升性能。
class Time { static start: number = 0; static info: number[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; } function getNum(num: number): number { let total: number = 348; const info = Time.info[num - Time.start]; / / 从 循 环 中 提 取 不 变 量 for (let index: number = 0x8000; index > 0x8; index >>= 1) { if ((info & index) != 0) { total++; } } return total; } -
闭包性能瓶颈
作用域链延长,内存占用增加,易导致泄漏。在性能敏感场景中,建议使用参数传递函数外的变量替代。
使用闭包会造成额外的开销。在性能敏感场景中,建议使用参数传递函数外的变量替代。let arr = [0, 1, 2] function foo(): number { return arr[0] + arr[1] } foo()建议使用参数传递函数外部的变量,以替代使用闭包。
let arr = [0, 1, 2]; function foo(array: number[]): number { return array[0] + array[1]; } foo(arr); -
可选参数性能影响
引擎需要处理undefined值,这会增加额外的分支判断和类型检查开销,降低函数执行效率。
优化前(使用可选参数)function add(left?: number, right?: number): number | undefined { if (left != undefined && right != undefined) { return left + right; } return undefined; }优化后(必选参数)
function add(left: number = 0, right: number = 0): number { return left + right; }根据业务需求,将函数参数声明为必选参数。考虑使用默认参数。
-
TypedArray核心价值
针对采用二进制缓冲区(ArrayBuffer)进行存储,元素类型固定(如int8Array、Uint16Array、Float32Array等)。这使得它非常适合进行数值计算和大数据处理,因为它可以直接操作内存,避免了JavaScript动态类型带来的开销。const typedArray1 = Int8Array.from([1, 2, 3]); const typedArray2 = Int8Array.from([4, 5, 6]); let res = new Int8Array(3); for (let i = 0; i < 3; i++) { res[i] = typedArray1[i] + typedArray2[i]; } -
稀疏数组问题
内存浪费(空元素会浪费空间),且遍历效率低下(使用forEach时耗时比密集数组更高)。
数组元素类型不统一(如(number | string)[])会导致类型检查开销增大,并且JavaScript引擎难以进行有效的优化。 -
异常处理性能代价
中断正常的执行流程,进行堆栈展开和异常对象构造,是一项昂贵的操作。在高频调用或循环中频繁抛出和捕获异常,会显著导致主线程阻塞,降低应用响应速度。
提前条件判断: 在可能出错的操作前进行检查,避免异常发生。错误码代替异常: 建议使用错误码(如-1, null)来表示失败,而非抛出异常。
优化前function div(a: number, b: number): number { if (a <= 0 || b <= 0) { throw new Error('Invalid numbers.'); } return a / b; } function sum(num: number): number { let sum = 0 try { for (let t = 1; t < 100; t++) { sum += div(t, num); } } catch (e) { console.log(e.message); } return sum; }优化后
function div(a: number, b: number): number { if (a <= 0 || b <= 0) { return NaN; } return a / b; } function sum(num: number): number { let sum = 0 for (let t = 1; t < 100; t++) { if (t <= 0 || num <= 0) { console.log('Invalid numbers.') } sum += div(t, num); } return sum; } -
长列表优化效果对比
在实际应用开发中,长列表渲染(如商品列表、消息列表)是常见的性能瓶颈。当列表项数量庞大或内容复杂时,容易出现卡顿、掉帧甚至应用崩溃。@State data: ArticleListData | null = null; List({ space: Constants.SPACE_16 }) { if (this.data !== null) { LazyForEach(this.data, (item: LearningResource) => { ListItem() { // 完 成 列 表 项 渲 染 .... } .reuseId('article') }, (item: LearningResource) => item.id) } }优化策略:
• 列表:只渲染可视区域内的列表项。
• 数据懒加载:滚动到底部时再加载更多数据。
• 组件复用:避免频繁创建和销毁列表项组件。
• 减少重绘:优化列表项布局,避免复杂计算。
需要登录才能发表回复
请登录或注册以继续。