你是不是经常遇到这样的场景:产品经理扔过来一堆数据,要你快速处理展示;后端返回的数组结构复杂,需要层层筛选过滤;明明很简单的数据操作,却要写一大堆循环和判断...
别担心!今天这篇干货,就是来拯救你的。我将带你系统掌握JavaScript数组和对象的核心操作,学完立刻就能用在实际项目中。相信我,掌握这些技巧后,你的开发效率至少提升一倍!
数组基础:从创建到遍历
让我们从最基础的数组操作开始。数组就像是一个数据容器,能帮我们有序地存放各种信息。
创建数组有两种常用方式。第一种是用方括号,这是最简洁的写法:
1// 创建空数组 2let emptyArray = []; 3 4// 创建带有初始值的数组 5let fruits = ['苹果', '香蕉', '橙子']; 6
第二种是用Array构造函数,适合动态创建数组:
1// 创建指定长度的空数组 2let arrayWithLength = new Array(5); 3 4// 创建带有初始值的数组 5let numbers = new Array(1, 2, 3, 4, 5); 6
数组创建好了,接下来看看怎么遍历。最传统的是for循环:
1let scores = [85, 92, 78, 96]; 2 3for (let i = 0; i < scores.length; i++) { 4 console.log([`第${i}个分数是:${scores[i]}`](https://xplanc.org/primers/document/zh/03.HTML/EX.HTML%20%E5%85%83%E7%B4%A0/EX.i.md)); 5} 6
但现代JavaScript提供了更优雅的forEach方法:
1scores.forEach((score, index) => { 2 console.log(`第${index}个分数是:${score}`); 3}); 4
看到区别了吗?forEach更简洁,不需要手动控制索引,代码可读性也更好。
数组高阶操作:过滤、映射、聚合
掌握了基础,我们来点高级的。这几个方法堪称数组操作的“三剑客”,能帮你解决80%的数据处理需求。
先看filter方法,它就像个筛子,帮你过滤出符合条件的数据:
1let products = [ 2 { name: '手机', price: 2999, inStock: true }, 3 { name: '耳机', price: 399, inStock: false }, 4 { name: '充电宝', price: 199, inStock: true } 5]; 6 7// 筛选有库存的商品 8let availableProducts = products.filter(product => product.inStock); 9console.log(availableProducts); 10// 输出:[{ name: '手机', price: 2999, inStock: true }, { name: '充电宝', price: 199, inStock: true }] 11
再看map方法,它能对数组中的每个元素进行转换,生成一个新数组:
1// 提取商品名称 2let productNames = products.map(product => product.name); 3console.log(productNames); 4// 输出:['手机', '耳机', '充电宝'] 5 6// 给所有商品打8折 7let discountedProducts = products.map(product => ({ 8 ...product, 9 price: product.price * 0.8 10})); 11
最后是reduce方法,它能把数组聚合成单个值,适合做求和、统计等操作:
1let orderItems = [ 2 { name: 'T恤', price: 99, quantity: 2 }, 3 { name: '牛仔裤', price: 199, quantity: 1 }, 4 { name: '帽子', price: 59, quantity: 3 } 5]; 6 7// 计算订单总金额 8let totalAmount = orderItems.reduce((sum, item) => { 9 return sum + (item.price * item.quantity); 10}, 0); 11console.log(totalAmount); // 输出:99*2 + 199*1 + 59*3 = 634 12
这三个方法组合使用,威力更大。比如我想统计有库存商品的总价值:
1let totalStockValue = products 2 .filter(product => product.inStock) 3 .map(product => product.price) 4 .reduce((sum, price) => sum + price, 0); 5
这种链式调用的写法既清晰又高效,强烈推荐大家在项目中多用。
对象操作:增删改查全掌握
说完了数组,我们来看看对象。对象在JavaScript中无处不在,掌握它的操作同样重要。
创建对象最常用的方式是字面量语法:
1let user = { 2 name: '张三', 3 age: 25, 4 email: 'zhangsan@example.com', 5 hobbies: ['读书', '游泳', '编程'] 6}; 7
访问对象属性有两种方式,点号和方括号:
1// 点号访问 - 适合已知属性名 2console.log(user.name); // 输出:张三 3 4// 方括号访问 - 适合动态属性名 5let property = 'age'; 6console.log(user[property]); // 输出:25 7
添加和修改属性很简单,直接赋值就行:
1// 添加新属性 2user.phone = '13800138000'; 3 4// 修改已有属性 5user.age = 26; 6
删除属性用delete操作符:
1delete user.phone; 2
有时候我们需要遍历对象的所有属性,可以用Object.keys、Object.values和Object.entries:
1// 获取所有属性名 2let keys = Object.keys(user); 3console.log(keys); // 输出:['name', 'age', 'email', 'hobbies'] 4 5// 获取所有属性值 6let values = Object.values(user); 7 8// 获取键值对数组 9let entries = Object.entries(user); 10entries.forEach(([key, value]) => { 11 console.log(`${key}: ${value}`); 12}); 13
实战演练:处理真实业务数据
理论说再多,不如来个真实案例。假设我们拿到了这样的订单数据:
1let orders = [ 2 { 3 id: 1, 4 customer: '张三', 5 items: [ 6 { name: '手机', price: 2999, category: '数码' }, 7 { name: '手机壳', price: 49, category: '配件' } 8 ], 9 status: '已完成' 10 }, 11 { 12 id: 2, 13 customer: '李四', 14 items: [ 15 { name: '耳机', price: 399, category: '数码' }, 16 { name: '贴膜', price: 29, category: '配件' } 17 ], 18 status: '待付款' 19 } 20]; 21
现在产品经理提了几个需求,我们来看看怎么实现。
需求1:统计每个订单的总金额
1let ordersWithTotal = orders.map(order => { 2 let total = order.items.reduce((sum, item) => sum + item.price, 0); 3 return { 4 ...order, 5 total: total 6 }; 7}); 8
需求2:找出所有包含数码产品的订单
1let digitalOrders = orders.filter(order => 2 order.items.some(item => item.category === '数码') 3); 4
需求3:按客户分组订单
1let ordersByCustomer = orders.reduce((groups, order) => { 2 if (!groups[order.customer]) { 3 groups[order.customer] = []; 4 } 5 groups[order.customer].push(order); 6 return groups; 7}, {}); 8
看到没?用对了方法,复杂的数据处理也能变得很简单。
性能优化:避免常见的坑
虽然这些方法很好用,但在实际项目中要注意性能问题。特别是处理大数据量时,一些细节会影响整体性能。
比如,在循环内创建函数就是个常见的性能陷阱:
1// 不推荐:每次循环都创建新函数 2array.forEach(item => { 3 someElement.addEventListener('click', () => { 4 console.log(item); 5 }); 6}); 7 8// 推荐:提前定义函数 9function handleClick(item) { 10 console.log(item); 11} 12array.forEach(item => { 13 someElement.addEventListener('click', handleClick.bind(null, item)); 14}); 15
还有,链式调用虽然优雅,但会产生中间数组。数据量大时可以考虑用循环替代:
1// 链式调用 - 可读性好 2let result = bigArray 3 .filter(x => x.active) 4 .map(x => x.value) 5 .reduce((sum, val) => sum + val, 0); 6 7// 循环 - 性能更好 8let sum = 0; 9for (let i = 0; i < bigArray.length; i++) { 10 if (bigArray[i].active) { 11 sum += bigArray[i].value; 12 } 13} 14
根据实际情况选择合适的方法,既要代码清晰,也要考虑性能。
现代JavaScript新特性
ES6以后,JavaScript提供了很多便利的新特性,让数组和对象操作更加方便。
解构赋值让提取数据变得超级简单:
1let person = { 2 name: '王五', 3 age: 30, 4 address: { 5 city: '北京', 6 street: '朝阳路' 7 } 8}; 9 10// 传统方式 11let name = person.name; 12let age = person.age; 13 14// 解构赋值 15let { name, age, address: { city } } = person; 16
展开运算符(...)让数组合并和对象合并变得优雅:
1// 数组合并 2let arr1 = [1, 2, 3]; 3let arr2 = [4, 5, 6]; 4let combined = [...arr1, ...arr2]; 5 6// 对象合并 7let baseInfo = { name: '赵六', age: 28 }; 8let detailInfo = { job: '工程师', salary: 15000 }; 9let fullInfo = { ...baseInfo, ...detailInfo }; 10
可选链(?.)和空值合并(??)让代码更加健壮:
1// 传统方式 - 需要层层判断 2let city = user && user.address && user.address.city; 3 4// 可选链 - 简洁安全 5let city = user?.address?.city; 6 7// 空值合并 - 提供默认值 8let displayName = user?.name ?? '匿名用户'; 9
这些新特性大大提升了代码的可读性和健壮性,建议大家尽快掌握。
总结与思考
今天我们系统学习了JavaScript数组和对象的核心操作。从基础的创建遍历,到高级的filter/map/reduce,再到实战案例和性能优化,相信你已经有了全面的认识。
《告别加班!这些数组操作技巧让前端开发效率翻倍》 是转载文章,点击查看原文。
