簡介
JS的性能沒法和C++比套利,有些編碼習(xí)慣會(huì)影響性能敦腔,優(yōu)先選擇高效的寫法雀瓢。
參考文章
高效寫法
- 變量默認(rèn)用const修飾翎卓,編譯不過了改成let
const index = 10000; // 該變量在后續(xù)過程中未發(fā)生改變纵潦,建議聲明成常量
- 避免整形和浮點(diǎn)型混用泪掀。既然這樣听绳,為什么不推出int和double關(guān)鍵字,非要弄個(gè)number异赫?
let intNum = 1;
intNum = 1.1; // 該變量在聲明時(shí)為整型數(shù)據(jù)椅挣,建議后續(xù)不要賦值浮點(diǎn)型數(shù)據(jù)
let doubleNum = 1.1;
doubleNum = 1; // 該變量在聲明時(shí)為浮點(diǎn)型數(shù)據(jù)头岔,建議后續(xù)不要賦值整型數(shù)據(jù)
- 循環(huán)中常量提取,減少屬性訪問次數(shù)
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) {
// 此處會(huì)多次對Time的info及start進(jìn)行查找鼠证,并且每次查找出來的值是相同的
total += ((Time.info[num - Time.start] & index) !== 0) ? 1 : 0;
}
return total;
}
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]; // 從循環(huán)中提取不變量
for (let index: number = 0x8000; index > 0x8; index >>= 1) {
if ((info & index) != 0) {
total++;
}
}
return total;
}
- 使用參數(shù)傳遞函數(shù)外的變量
/// 使用閉包會(huì)造成額外的閉包創(chuàng)建和訪問開銷
let arr = [0, 1, 2];
function foo(): number {
return arr[0] + arr[1];
}
foo();
/// 使用參數(shù)傳遞函數(shù)外的變量來替代使用閉包峡竣。
let arr = [0, 1, 2];
function foo(array: number[]): number {
return array[0] + array[1];
}
foo(arr);
- 避免使用可選參數(shù),用默認(rèn)參數(shù)替代
/// 函數(shù)的可選參數(shù)表示參數(shù)可能為undefined量九,在函數(shù)內(nèi)部使用該參數(shù)時(shí)适掰,需要進(jìn)行非空值的判斷,造成額外的開銷荠列。
function add(left?: number, right?: number): number | undefined {
if (left != undefined && right != undefined) {
return left + right;
}
return undefined;
}
/// 使用默認(rèn)參數(shù)类浪,減少空判斷,提高性能
function add(left: number = 0, right: number = 0): number {
return left + right;
}
- 數(shù)值數(shù)組推薦使用TypedArray肌似,既然這樣费就,推出number類型的意義在哪里?恢復(fù)int和double不是更好川队?
/// 純數(shù)字力细,用number性能低
const arr1 = new Array<number>([1, 2, 3]);
const arr2 = new Array<number>([4, 5, 6]);
let res = new Array<number>(3);
for (let i = 0; i < 3; i++) {
res[i] = arr1[i] + arr2[i];
}
const typedArray1 = new Int8Array([1, 2, 3]);
const typedArray2 = new Int8Array([4, 5, 6]);
let res = new Int8Array(3);
for (let i = 0; i < 3; i++) {
res[i] = typedArray1[i] + typedArray2[i];
}
- 運(yùn)行時(shí)在分配超過1024大小的數(shù)組或者針對稀疏數(shù)組,會(huì)采用hash表的方式來存儲(chǔ)元素呼寸。在該模式下艳汽,相比于用偏移訪問數(shù)組元素速度較慢。在代碼開發(fā)時(shí)对雪,應(yīng)盡量避免數(shù)組變成稀疏數(shù)組河狐。
// 直接分配100000大小的數(shù)組,運(yùn)行時(shí)會(huì)處理成用hash表來存儲(chǔ)元素
let count = 100000;
let result: number[] = new Array(count);
// 創(chuàng)建數(shù)組后瑟捣,直接在9999處賦值馋艺,會(huì)變成稀疏數(shù)組
let result: number[] = new Array();
result[9999] = 0;
- 避免使用聯(lián)合類型數(shù)組
let arrNum: number[] = [1, 1.1, 2]; // 數(shù)值數(shù)組中混合使用整型數(shù)據(jù)和浮點(diǎn)型數(shù)據(jù)
let arrUnion: (number | string)[] = [1, 'hello']; // 聯(lián)合類型數(shù)組
/// 根據(jù)業(yè)務(wù)需要,將相同類型的數(shù)據(jù)放置在同一數(shù)組中
let arrInt: number[] = [1, 2, 3];
let arrDouble: number[] = [0.1, 0.2, 0.3];
let arrString: string[] = ['hello', 'world'];
- 避免頻繁拋出異常
/// 創(chuàng)建異常時(shí)會(huì)構(gòu)造異常的棧幀迈套,造成性能損耗捐祠。
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
}
/// 用特殊值NaN替代異常,提高性能
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
}