已知需求從數(shù)組中查詢滿足特定條件的值,我開始用的 forEach陷谱,因?yàn)橛泻芏嘀敌枰樵兝硬看味家h(huán)一遍數(shù)組,我就想直接用 for 循環(huán)是不是要快一些烟逊,于是想比較一下 for forEach map 三個誰快一些渣窜。
const tempArr = Array.from({ length: 1000 }).map(s => ({ name: ~~(Math.random() * 1000) }));
console.time('for');
const forArr = [];
for (let i = 0; i < tempArr.length; i++) {
if (tempArr[i] === 233) forArr.push(tempArr[i]);
}
console.timeEnd('for');
console.time('forEach');
const forEachArr = [];
tempArr.forEach(s => {
if (s === 233) forEachArr.push(s);
})
console.timeEnd('forEach');
console.time('map');
const mapArr = [];
tempArr.map(s => {
if (s === 233) mapArr.push(s);
});
console.timeEnd('map');
經(jīng)過測試,這三者大概有 30% 的差距宪躯,但是速度并不是一直 for > forEach > map乔宿,運(yùn)行多次,有時候 for 可能最慢访雪,map 最快详瑞。
于是我打算上網(wǎng)搜一下,在看了一些文章和資料后臣缀,我突然意識到優(yōu)化不是這樣打的坝橡。
性能優(yōu)化什么的,應(yīng)該是底層優(yōu)化精置,而不是語法的選擇计寇,像這類語法糖更多的是提供語義化和便捷性。
- forEach 可以更方便的循環(huán)遍歷
- map 除了循環(huán)遍歷還會返回一個數(shù)組
“過早優(yōu)化是萬惡之源”氯窍,能力不夠的時候會往錯誤的方向使勁饲常。
那么回到問題,我是想要減少循環(huán)次數(shù)狼讨,那直接用對象的 key 取值更快啊。只需要處理一次原數(shù)組柒竞,就不用每次都循環(huán)了政供。
通過測試,我發(fā)現(xiàn) map 和 forEach 的差距并沒有那么大,于是我打算查看一下他們的實(shí)現(xiàn)布隔。
// Production steps of ECMA-262, Edition 5, 15.4.4.19
// Reference: http://es5.github.io/#x15.4.4.19
if (!Array.prototype.map) {
Array.prototype.map = function (callback/*, thisArg*/) {
var T, A, k;
if (this == null) {
throw new TypeError('this is null or not defined');
}
var O = Object(this);
var len = O.length >>> 0;
if (typeof callback !== 'function') {
throw new TypeError(callback + ' is not a function');
}
if (arguments.length > 1) {
T = arguments[1];
}
A = new Array(len);
k = 0;
while (k < len) {
var kValue, mappedValue;
if (k in O) {
kValue = O[k];
mappedValue = callback.call(T, kValue, k, O);
A[k] = mappedValue;
}
k++;
}
return A;
};
}
// Production steps of ECMA-262, Edition 5, 15.4.4.18
// Reference: http://es5.github.io/#x15.4.4.18
if (!Array.prototype.forEach) {
Array.prototype.forEach = function (callback/*, thisArg*/) {
var T, k;
if (this == null) {
throw new TypeError('this is null or not defined');
}
var O = Object(this);
var len = O.length >>> 0;
if (typeof callback !== 'function') {
throw new TypeError(callback + ' is not a function');
}
if (arguments.length > 1) {
T = arguments[1];
}
k = 0;
while (k < len) {
var kValue;
if (k in O) {
kValue = O[k];
callback.call(T, kValue, k, O);
}
k++;
}
};
}
發(fā)現(xiàn)都是用到了 while 离陶,只是 map 多存了一個對象,對于目前前端的數(shù)據(jù)處理衅檀,這點(diǎn)消耗完全可以忽略招刨,但是可讀性就很重要了,明明不需要返回新數(shù)組哀军,結(jié)果使用了 map 沉眶,可能會給讀代碼的人造成一點(diǎn)點(diǎn)困擾。就像 div 可以做很多事杉适,但是官方還是推薦語義化標(biāo)簽谎倔。
好了,既然都寫到這里了猿推,俗話說“來都來了”片习,這里整理一下 JavaScript 中操作數(shù)組和對象的部分方法。
- while
const arr = [...];
let k = 0;
while( k < arr.length ) {
k++;
// do something
}
- for
- for-of
- for-in
const arr = [...];
for(let i = 0; i < arr.length; i++ ) {
// do something
}
for(let i of arr ) {
// do something
}
const dist = {};
for(let i in arr ) {
// do something
}
- forEach
const arr = [...];
arr.forEach((s,i)=>{
// do something
});
// thisArg
class Counter {
sum = 0;
count = 0;
add(array){
array.forEach( s => {
this.sum += s;
++this.count;
},this)
}
}
- map
const arr = [...];
const newArr = arr.map((s,i) => {
// do something
return xxx;
});
- reduce
- 接受一個判斷函數(shù)
- 迭代執(zhí)行該函數(shù)并返回最終結(jié)果
const arr= [3, 14,15, 9, 26];
const sum = arr.reduce(a,b) => a + b);
- filter
- 接收一個判斷函數(shù)
- 返回一個滿足條件的數(shù)組
const arr= [3, 14,15, 9, 26];
const res = arr.filter(s => s > 10); // [14,15,26]
- every
- 接收一個判斷函數(shù)
- 返回 true / false
- true:全滿足
- false:至少有一個不滿足
const arr= [3, 14,15, 9, 26];
arr.every(s => s < 30); // true
arr.every(s => s > 10); // false
- some
- 接收一個判斷函數(shù)
- 返回 true / false
- true:至少有一個滿足
- false:全不滿足
const arr= [3, 14,15, 9, 26];
arr.some(s => s < 30); // true
arr.some(s => s > 10); // true
arr.some(s => s < 0); // false
- find
- 接收一個判斷函數(shù)
- 返回滿足條件的第一個值
const arr= [3, 14,15, 9, 26];
const res = arr.find(s => s > 13); // 14
- findIndex
- 接收一個判斷函數(shù)
- 返回滿足條件的第一個值的 index
const arr= [3, 14,15, 9, 26];
const resIndex = arr.findIndex(s => s > 13); // 1
我是虛玩玩蹬叭,與君共勉~