for 循环// 传统 for 循环
for (let i = 0; i < 5; i++) {
console.log(i);
}
// 无限循环(避免使用)
// for (;;) {
// console.log("无限循环");
// }
// 多个变量
for (let i = 0, j = 10; i < j; i++, j--) {
console.log(`i=${i}, j=${j}`);
}
while 循环// while
let i = 0;
while (i < 5) {
console.log(i);
i++;
}
// do...while(至少执行一次)
let j = 0;
do {
console.log(j);
j++;
} while (j < 5);
for...in 循环// 遍历对象可枚举属性
const person = {
name: "张三",
age: 25,
city: "北京",
};
for (let key in person) {
console.log(`${key}: ${person[key]}`);
// name: 张三
// age: 25
// city: 北京
}
// 注意:会遍历原型链上的可枚举属性
const obj = { a: 1 };
const child = Object.create(obj);
child.b = 2;
for (let prop in child) {
console.log(prop); // b, a (来自原型链)
}
// 使用 hasOwnProperty 过滤
for (let prop in child) {
if (child.hasOwnProperty(prop)) {
console.log(prop); // b (只遍历自身属性)
}
}
for...of 循环 (ES6+)// 遍历可迭代对象的值
const arr = ["a", "b", "c"];
for (let value of arr) {
console.log(value); // a, b, c
}
// 遍历字符串
const str = "hello";
for (let char of str) {
console.log(char); // h, e, l, l, o
}
// 遍历 Map
const map = new Map([
["name", "张三"],
["age", 25],
]);
for (let [key, value] of map) {
console.log(`${key}: ${value}`);
// name: 张三
// age: 25
}
// 遍历 Set
const set = new Set([1, 2, 3, 3, 2]);
for (let value of set) {
console.log(value); // 1, 2, 3 (去重)
}
// 遍历 arguments 对象
function sum() {
let total = 0;
for (let num of arguments) {
total += num;
}
return total;
}
console.log(sum(1, 2, 3)); // 6
for await...of 循环 (ES2018+)// 遍历异步可迭代对象
async function processAsyncData() {
const asyncIterable = {
[Symbol.asyncIterator]() {
let i = 0;
return {
async next() {
if (i < 3) {
await new Promise(resolve => setTimeout(resolve, 1000));
return { value: i++, done: false };
}
return { done: true };
},
};
},
};
for await (let value of asyncIterable) {
console.log(value); // 0 (1秒后), 1 (1秒后), 2 (1秒后)
}
}
// 在 for 循环中使用
for (let i = 0; i < 10; i++) {
if (i === 5) {
break; // 当 i=5 时终止循环
}
console.log(i); // 0, 1, 2, 3, 4
}
// 在 while 循环中使用
let j = 0;
while (true) {
if (j === 5) {
break;
}
console.log(j); // 0, 1, 2, 3, 4
j++;
}
// 带标签的 break
outerLoop: for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
if (i === 1 && j === 1) {
break outerLoop; // 跳出外层循环
}
console.log(`i=${i}, j=${j}`);
// i=0, j=0
// i=0, j=1
// i=0, j=2
// i=1, j=0
}
}
// 跳过偶数
for (let i = 0; i < 10; i++) {
if (i % 2 === 0) {
continue; // 跳过当前迭代
}
console.log(i); // 1, 3, 5, 7, 9
}
// 带标签的 continue
outerLoop: for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
if (j === 1) {
continue outerLoop; // 跳过外层循环当前迭代
}
console.log(`i=${i}, j=${j}`);
// i=0, j=0
// i=1, j=0
// i=2, j=0
}
}
const numbers = [1, 2, 3, 4, 5];
// 基本用法
numbers.forEach(function (value, index, array) {
console.log(`索引 ${index}: 值 ${value}`);
});
// 箭头函数
numbers.forEach((value, index) => {
console.log(`numbers[${index}] = ${value}`);
});
// 无法中断或跳过
numbers.forEach(value => {
if (value === 3) return; // 仅跳过当前元素,不会中断循环
console.log(value); // 1, 2, 4, 5
});
const numbers = [1, 2, 3, 4, 5];
// 返回新数组
const doubled = numbers.map(num => num * 2);
console.log(doubled); // [2, 4, 6, 8, 10]
// 包含索引
const withIndex = numbers.map((num, index) => `${index}:${num}`);
console.log(withIndex); // ["0:1", "1:2", "2:3", "3:4", "4:5"]
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// 过滤偶数
const evens = numbers.filter(num => num % 2 === 0);
console.log(evens); // [2, 4, 6, 8, 10]
// 过滤大于5的数
const greaterThan5 = numbers.filter(num => num > 5);
console.log(greaterThan5); // [6, 7, 8, 9, 10]
const numbers = [1, 2, 3, 4, 5];
// 求和
const sum = numbers.reduce((accumulator, currentValue) => {
return accumulator + currentValue;
}, 0);
console.log(sum); // 15
// 求最大值
const max = numbers.reduce((acc, cur) => {
return cur > acc ? cur : acc;
}, numbers[0]);
console.log(max); // 5
// 统计字符出现次数
const chars = ["a", "b", "a", "c", "b", "a"];
const charCount = chars.reduce((acc, char) => {
acc[char] = (acc[char] || 0) + 1;
return acc;
}, {});
console.log(charCount); // {a: 3, b: 2, c: 1}
const users = [
{ id: 1, name: "张三", active: true },
{ id: 2, name: "李四", active: false },
{ id: 3, name: "王五", active: true },
];
// find - 查找第一个匹配的元素
const activeUser = users.find(user => user.active);
console.log(activeUser); // {id: 1, name: '张三', active: true}
// findIndex - 查找第一个匹配的索引
const inactiveIndex = users.findIndex(user => !user.active);
console.log(inactiveIndex); // 1
const numbers = [1, 2, 3, 4, 5];
// some - 是否有元素满足条件
const hasEven = numbers.some(num => num % 2 === 0);
console.log(hasEven); // true
// every - 是否所有元素都满足条件
const allPositive = numbers.every(num => num > 0);
console.log(allPositive); // true
const sentences = ["Hello world", "JavaScript is fun"];
// 先 map 后 flat
const words = sentences.flatMap(sentence => sentence.split(" "));
console.log(words); // ["Hello", "world", "JavaScript", "is", "fun"]
// 过滤并展开
const numbers = [1, 2, 3, 4];
const result = numbers.flatMap(num => (num % 2 === 0 ? [num, num * 2] : []));
console.log(result); // [2, 4, 4, 8]
const arr = new Array(1000000).fill(0);
// 性能测试
console.time("for循环");
for (let i = 0, len = arr.length; i < len; i++) {
// 操作
}
console.timeEnd("for循环");
console.time("forEach");
arr.forEach(() => {
// 操作
});
console.timeEnd("forEach");
console.time("for...of");
for (let value of arr) {
// 操作
}
console.timeEnd("for...of");
// 1. 缓存数组长度
const arr = [1, 2, 3, 4, 5];
for (let i = 0, len = arr.length; i < len; i++) {
// 避免每次循环都计算 length
}
// 2. 倒序循环(某些情况下更快)
for (let i = arr.length - 1; i >= 0; i--) {
// 操作
}
// 3. 避免在循环中创建函数
// 不好
for (let i = 0; i < 10; i++) {
arr[i].onclick = function () {
console.log(i); // 创建了10个函数
};
}
// 好
function createHandler(i) {
return function () {
console.log(i);
};
}
for (let i = 0; i < 10; i++) {
arr[i].onclick = createHandler(i);
}
// 4. 使用合适的迭代方法
const numbers = [1, 2, 3, 4, 5];
// 需要新数组时用 map
const doubled = numbers.map(n => n * 2);
// 需要过滤时用 filter
const evens = numbers.filter(n => n % 2 === 0);
// 需要查找时用 find/findIndex
const firstEven = numbers.find(n => n % 2 === 0);
// 需要检查条件时用 some/every
const hasEven = numbers.some(n => n % 2 === 0);
const sparse = [1, , 3, , 5]; // 有空洞的数组
// for 循环
for (let i = 0; i < sparse.length; i++) {
console.log(sparse[i]); // 1, undefined, 3, undefined, 5
}
// forEach 会跳过空洞
sparse.forEach(value => {
console.log(value); // 1, 3, 5
});
// for...of 不会跳过
for (let value of sparse) {
console.log(value); // 1, undefined, 3, undefined, 5
}
const obj = { a: 1, b: 2, c: 3 };
// 获取键数组
const keys = Object.keys(obj); // ['a', 'b', 'c']
// 获取值数组
const values = Object.values(obj); // [1, 2, 3]
// 获取键值对数组
const entries = Object.entries(obj); // [['a', 1], ['b', 2], ['c', 3]]
// 使用 for...of 遍历 entries
for (let [key, value] of Object.entries(obj)) {
console.log(`${key}: ${value}`);
}
const products = [
{ id: 1, name: "Laptop", price: 1000, category: "Electronics", stock: 10 },
{ id: 2, name: "Mouse", price: 50, category: "Electronics", stock: 100 },
{ id: 3, name: "Chair", price: 200, category: "Furniture", stock: 5 },
{ id: 4, name: "Desk", price: 500, category: "Furniture", stock: 2 },
];
// 链式调用处理数据
const result = products
.filter(product => product.category === "Electronics") // 过滤电子产品
.filter(product => product.price > 100) // 价格大于100
.map(product => ({
// 转换格式
name: product.name.toUpperCase(),
price: `$${product.price}`,
value: product.price * product.stock,
}))
.sort((a, b) => b.value - a.value); // 按价值降序排序
console.log(result);