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