# for、forEach、for ...of
- for、for of 中可以通过 continue、break 等跳出或者中断循环;
- 对于 for in 是不起作用;
- forEach 无法跳出循环,如果在 forEach 中写 continue 或者 break 会直接抛出异常;
- for of 与 for 如果数组中存在空元素,同样会执行
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
});
// 打印索引值
for (const item in list) {
if (item === 5) {
break; // 0 1 2 3 5 6 7 9 10
// continue; // 0 1 2 3 5 6 7 9 10
}
console.log(item);
}
# some、every
- 二者都是用来做数组条件判断的,都是返回一个布尔值
- 二者都可以被中断
- some 若某一元素满足条件,返回 true,循环中断;所有元素不满足条件,返回 false。
- every 与 some 相反,若有一元素不满足条件,返回 false,循环中断;所有元素满足条件,返回 true。
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
- 二者都是生成一个新数组,都不会改变原数组(不包括遍历对象数组是,在回调函数中操作元素对象)
- 二者都会跳过空元素。
- map 会将回调函数的返回值组成一个新数组,数组长度与原数组一致。
- filter 会将符合回调函数条件的元素组成一个新数组,数组长度与原数组不同。
- map 生成的新数组元素是可自定义。
- filter 生成的新数组元素不可自定义,与对应原数组元素一致。
- map 还是不能通过 continue、break 进行中断。
- map、filter 返回的结果不是进行深拷贝的结果。
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
- 二者都是用来查找数组元素。
- find 方法返回数组中满足 callback 函数的第一个元素的值。如果不存在返回 undefined。
- findIndex 它返回数组中找到的元素的索引,而不是其值,如果不存在返回 -1。
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 上解释为累计器,但我觉得不恰当,按我的理解它应该是截至当前元素,之前所有的数组元素被回调函数处理累计的结果。
- current:当前被执行的数组元素。
- currentIndex: 当前被执行的数组元素索引。
- sourceArray:原数组,也就是调用 reduce 方法的数组。
如果不传入初始值,reduce 方法会从索引 1 开始执行回调函数,如果传入初始值,将从索引 0 开始、并从初始值的基础上累计执行回调。
# 计算对象数组某一属性的总和
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 }
有关其他 reduce 的用法:https://juejin.cn/post/6844904063729926152
# 性能对比
# 对象属性遍历
# for in
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 过滤
*/
使用 for in 循环时,返回的是所有能够通过对象访问的、可枚举的属性,既包括存在于实例中的属性,也包括存在于原型中的实例。如果只需要获取对象的实例属性,可以使用 hasOwnProperty 进行过滤。 for in 的循环顺序,参考【JavaScript 权威指南】(第七版)6.6.1。
- 先列出名字为非负整数的字符串属性,按照数值顺序从最小到最大。这条规则意味着数组和类数组对象的属性会按照顺序被枚举。
- 在列出类数组索引的所有属性之后,在列出所有剩下的字符串名字(包括看起来像整负数或浮点数的名字)的属性。这些属性按照它们添加到对象的先后顺序列出。对于在对象字面量中定义的属性,按照他们在字面量中出现的顺序列出。
- 最后,名字为符号对象的属性按照它们添加到对象的先后顺序列出。
# Object.keys
用于获取对象自身所有的可枚举的属性值,但不包括原型中的属性,然后返回一个由属性名组成的数组。
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']
const obj1 = { a: 'a', b: 'b'}
console.log(Object.keys(obj1)); // ["a", "b"]
# Object.values
用于获取对象自身所有的可枚举的属性值,但不包括原型中的属性,然后返回一个由属性值组成的数组。
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']
# Object.entries
用于获取对象自身所有的可枚举的属性值,但不包括原型中的属性,然后返回二维数组。每一个子数组由对象的属性名、属性值组成。可以同时拿到属性名与属性值的方法。
const str = 'ab';
for (const [key, value] of Object.entries(str)) {
console.log(`${key}: ${value}`);
}
// 0: a
// 1: b
const arr = ['a', 'b'];
for (const [key, value] of Object.entries(arr)) {
console.log(`${key}: ${value}`);
}
// 0: a
// 1: b
const obj = { 1: 'b', 0: 'a' };
for (const [key, value] of Object.entries(obj)) {
console.log(`${key}: ${value}`);
}
// 0: a
// 1: b
# Object.getOwnPropertyNames
用于获取对象自身所有的可枚举的属性值,但不包括原型中的属性,然后返回一个由属性名组成的数组。
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']
参考:链接:https://juejin.cn/post/6966390357005172773