陣列和物件在各種程式語言中都扮演著至關重要的角色,本篇文章為大家介紹一下JavaScript中常用陣列遍歷、物件遍歷的方法和各方法間的差異,以及使用時的注意事項。
#隨著 JS 的不斷發展,截至 ES7 規格已經有十多種遍歷方法。以下依照功能類似的方法為一組,來介紹數組常用的遍歷方法。
for、forEach、for ...of
const list = [1, 2, 3, 4, 5, 6, 7, 8,, 10, 11]; for (let i = 0, len = list.length; i < len; i++) { if (list[i] === 5) { break; // 1 2 3 4 // continue; // 1 2 3 4 6 7 8 undefined 10 11 } console.log(list[i]); } for (const item of list) { if (item === 5) { break; // 1 2 3 4 // continue; // 1 2 3 4 6 7 8 undefined 10 11 } console.log(item); } list.forEach((item, index, arr) => { if (item === 5) return; console.log(index); // 0 1 2 3 5 6 7 9 10 console.log(item); // 1 2 3 4 6 7 8 10 11 });
小結
some、every
const list = [ { name: '头部导航', backward: false }, { name: '轮播', backward: true }, { name: '页脚', backward: false }, ]; const someBackward = list.some(item => item.backward); // someBackward: true const everyNewest = list.every(item => !item.backward); // everyNewest: false
小結
filter、map
const list = [ { name: '头部导航', type: 'nav', id: 1 },, { name: '轮播', type: 'content', id: 2 }, { name: '页脚', type: 'nav', id: 3 }, ]; const resultList = list.filter(item => { console.log(item); return item.type === 'nav'; }); // resultList: [ // { name: '头部导航', type: 'nav', id: 1 }, // { name: '页脚', type: 'nav', id: 3 }, // ] const newList = list.map(item => { console.log(item); return item.id; }); // newList: [1, empty, 2, 3] // list: [ // { name: '头部导航', type: 'nav', id: 1 }, // empty, // { name: '轮播', type: 'content', id: 2 }, // { name: '页脚', type: 'nav', id: 3 }, // ]
小結
##二者都是產生一個新數組,都不會改變原始數組(不包括遍歷物件數組是,在回呼函數中操作元素物件)find、findIndex#const list = [
{ name: '头部导航', id: 1 },
{ name: '轮播', id: 2 },
{ name: '页脚', id: 3 },
];
const result = list.find((item) => item.id === 3);
// result: { name: '页脚', id: 3 }
result.name = '底部导航';
// list: [
// { name: '头部导航', id: 1 },
// { name: '轮播', id: 2 },
// { name: '底部导航', id: 3 },
// ]
const index = list.findIndex((item) => item.id === 3);
// index: 2
list[index].name // '底部导航';
二者都是用來找出數組元素。
reduce、reduceRight#reduce 方法接收兩個參數,第一個參數是回呼函數(callback) ,第二個參數是初始值(initialValue)。
reduceRight 方法除了與reduce執行方向相反外(從右往左),其他完全與其一致。
回呼函數接收四個參數:
accumulator:MDN 上解釋為累計器,但我覺得不恰當,按我的理解它應該是截至當前元素,之前所有的數組元素被回調函數處理累計的結果。const list = [
{ name: 'left', width: 20 },
{ name: 'center', width: 70 },
{ name: 'right', width: 10 },
];
const total = list.reduce((currentTotal, item) => {
return currentTotal + item.width;
}, 0);
// total: 100
const list = [
{ name: 'left', width: 20 },
{ name: 'right', width: 10 },
{ name: 'center', width: 70 },
{ name: 'right', width: 10 },
{ name: 'left', width: 20 },
{ name: 'right', width: 10 },
];
const repeatTime = {};
const result = list.reduce((array, item) => {
if (repeatTime[item.name]) {
repeatTime[item.name]++;
return array;
}
repeatTime[item.name] = 1;
return [...array, item];
}, []);
// repeatTime: { left: 2, right: 3, center: 1 }
// result: [
// { name: 'left', width: 20 },
// { name: 'right', width: 10 },
// { name: 'center', width: 70 },
// ]
const list = [
{ name: 'left', width: 20 },
{ name: 'right', width: 30 },
{ name: 'center', width: 70 },
{ name: 'top', width: 40 },
{ name: 'bottom', width: 20 },
];
const max = list.reduce((curItem, item) => {
return curItem.width >= item.width ? curItem : item;
});
const min = list.reduce((curItem, item) => {
return curItem.width <= item.width ? curItem : item;
});
// max: { name: "center", width: 70 }
// min: { name: "left", width: 20 }
var list = Array(100000).fill(1) console.time('for'); for (let index = 0, len = list.length; index < len; index++) { } console.timeEnd('for'); // for: 2.427642822265625 ms console.time('every'); list.every(() => { return true }) console.timeEnd('every') // some: 2.751708984375 ms console.time('some'); list.some(() => { return false }) console.timeEnd('some') // some: 2.786590576171875 ms console.time('foreach'); list.forEach(() => {}) console.timeEnd('foreach'); // foreach: 3.126708984375 ms console.time('map'); list.map(() => {}) console.timeEnd('map'); // map: 3.743743896484375 ms console.time('forof'); for (let index of list) { } console.timeEnd('forof') // forof: 6.33380126953125 ms
從列印結果可以看出,for 迴圈的速度最快,for of 迴圈最慢
常用遍歷的終止、效能表格比較 最后,不同浏览器内核 也会有些差异,有兴趣的同学也可以尝试一下。 在对象遍历中,经常需要遍历对象的键、值,ES5 提供了 for...in 用来遍历对象,然而其涉及对象属性的“可枚举属性”、原型链属性等,下面将从 Object 对象本质探寻各种遍历对象的方法,并区分常用方法的一些特点。 for in 小结 使用 for in 循环时,返回的是所有能够通过对象访问的、可枚举的属性,既包括存在于实例中的属性,也包括存在于原型中的实例。如果只需要获取对象的实例属性,可以使用 hasOwnProperty 进行过滤。 使用时,要使用 for in 的循环顺序,参考【JavaScript 权威指南】(第七版)6.6.1。 Object.keys 小结 用于获取对象自身所有的可枚举的属性值,但不包括原型中的属性,然后返回一个由属性名组成的数组。 Object.values 小结 用于获取对象自身所有的可枚举的属性值,但不包括原型中的属性,然后返回一个由属性值组成的数组。 Object.entries 小结 用于获取对象自身所有的可枚举的属性值,但不包括原型中的属性,然后返回二维数组。每一个子数组由对象的属性名、属性值组成。可以同时拿到属性名与属性值的方法。 Object.getOwnPropertyNames 小结 用于获取对象自身所有的可枚举的属性值,但不包括原型中的属性,然后返回一个由属性名组成的数组。 我们对比了多种常用遍历的方法的差异,在了解了这些之后,我们在使用的时候需要好好思考一下,就能知道那个方法是最合适的。欢迎大家纠正补充。 更多编程相关知识,请访问:编程视频!! 以上是在淺談JavaScript中遍歷數組和物件的幾種常用方法的詳細內容。更多資訊請關注PHP中文網其他相關文章!是否可终止 ** break continue return 性能(ms) for 终止 ✅ 跳出本次循环 ✅ ❌ 2.42 forEach ❌ ❌ ❌ 3.12 map ❌ ❌ ❌ 3.74 for of 终止 ✅ 跳出本次循环 ✅ ❌ 6.33 some ❌ ❌ return true ✅ 2.78 every ❌ ❌ return false ✅ 2.75 对象遍历
Object.prototype.fun = () => {};const obj = { 2: 'a', 1: 'b' };for (const i in obj) { console.log(i, ':', obj[i]);}// 1: b// 2: a// fun : () => {} Object 原型链上扩展的方法也被遍历出来for (const i in obj) { if (Object.prototype.hasOwnProperty.call(obj, i)) { console.log(i, ':', obj[i]); }}// name : a 不属于自身的属性将被 hasOwnProperty 过滤
(const x in a)
而不是(x in a)
后者将会创建一个全局变量。Object.prototype.fun = () => {};const str = 'ab';console.log(Object.keys(str));// ['0', '1']const arr = ['a', 'b'];console.log(Object.keys(arr));// ['0', '1']const obj = { 1: 'b', 0: 'a' };console.log(Object.keys(obj));// ['0', '1']
Object.prototype.fun = () => {};const str = 'ab';console.log(Object.values(str));// ['a', 'b']const arr = ['a', 'b'];console.log(Object.values(arr));// ['a', 'b']const obj = { 1: 'b', 0: 'a' };console.log(Object.values(obj));// ['a', 'b']
const str = 'ab';for (const [key, value] of Object.entries(str)) { console.log(`${key}: ${value}`);}// 0: a// 1: bconst arr = ['a', 'b'];for (const [key, value] of Object.entries(arr)) { console.log(`${key}: ${value}`);}// 0: a// 1: bconst obj = { 1: 'b', 0: 'a' };for (const [key, value] of Object.entries(obj)) { console.log(`${key}: ${value}`);}// 0: a// 1: b
Object.prototype.fun = () => {};Array.prototype.fun = () => {};const str = 'ab';console.log(Object.getOwnPropertyNames(str));// ['0', '1', 'length']const arr = ['a', 'b'];console.log(Object.getOwnPropertyNames(arr));// ['0', '1', 'length']const obj = { 1: 'b', 0: 'a' };console.log(Object.getOwnPropertyNames(obj));// ['0', '1']
总结