JavaScript 数组与对象

章节介绍

数组和对象是 JavaScript 中最重要的两种数据结构,它们让我们能够组织和处理复杂的数据。数组用于存储有序的数据集合,对象用于存储键值对数据。本教程将详细介绍数组和对象的操作方法,帮助您掌握数据处理的核心技能。

核心知识点

数组基础

数组是有序的数据集合,可以存储任意类型的值。

// 创建数组
let fruits = ['苹果', '香蕉', '橙子'];
let numbers = [1, 2, 3, 4, 5];
let mixed = ['字符串', 42, true, null, undefined];

// 访问数组元素
console.log(fruits[0]);    // 苹果(第一个元素)
console.log(fruits[1]);    // 香蕉(第二个元素)
console.log(fruits[fruits.length - 1]);  // 橙子(最后一个元素)

// 数组长度
console.log(fruits.length);  // 3

// 修改数组元素
fruits[0] = '葡萄';
console.log(fruits);  // ['葡萄', '香蕉', '橙子']

// 添加元素到数组末尾
fruits.push('草莓');
console.log(fruits);  // ['葡萄', '香蕉', '橙子', '草莓']

// 从数组末尾删除元素
let lastFruit = fruits.pop();
console.log(lastFruit);  // 草莓
console.log(fruits);  // ['葡萄', '香蕉', '橙子']

// 添加元素到数组开头
fruits.unshift('西瓜');
console.log(fruits);  // ['西瓜', '葡萄', '香蕉', '橙子']

// 从数组开头删除元素
let firstFruit = fruits.shift();
console.log(firstFruit);  // 西瓜
console.log(fruits);  // ['葡萄', '香蕉', '橙子']

数组遍历方法

JavaScript 提供了多种遍历数组的方法:

forEach

const numbers = [1, 2, 3, 4, 5];

numbers.forEach((num, index, array) => {
  console.log(`索引 ${index}: ${num}`);
});

// 输出:
// 索引 0: 1
// 索引 1: 2
// 索引 2: 3
// 索引 3: 4
// 索引 4: 5

map

const numbers = [1, 2, 3, 4, 5];

// 创建新数组,每个元素乘以 2
const doubled = numbers.map(num => num * 2);
console.log(doubled);  // [2, 4, 6, 8, 10]

// 创建新数组,将数字转换为字符串
const stringNumbers = numbers.map(num => `数字:${num}`);
console.log(stringNumbers);  // ['数字:1', '数字:2', '数字:3', '数字:4', '数字:5']

filter

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 greaterThanFive = numbers.filter(num => num > 5);
console.log(greaterThanFive);  // [6, 7, 8, 9, 10]

reduce

const numbers = [1, 2, 3, 4, 5];

// 计算总和
const sum = numbers.reduce((acc, num) => acc + num, 0);
console.log(sum);  // 15

// 计算乘积
const product = numbers.reduce((acc, num) => acc * num, 1);
console.log(product);  // 120

// 找到最大值
const max = numbers.reduce((acc, num) => Math.max(acc, num), numbers[0]);
console.log(max);  // 5

// 统计元素出现次数
const words = ['apple', 'banana', 'apple', 'orange', 'banana', 'apple'];
const wordCount = words.reduce((acc, word) => {
  acc[word] = (acc[word] || 0) + 1;
  return acc;
}, {});

console.log(wordCount);  // { apple: 3, banana: 2, orange: 1 }

find 和 findIndex

const users = [
  { id: 1, name: '张三', age: 25 },
  { id: 2, name: '李四', age: 30 },
  { id: 3, name: '王五', age: 28 }
];

// 找到第一个符合条件的元素
const user = users.find(u => u.age > 26);
console.log(user);  // { id: 2, name: '李四', age: 30 }

// 找到第一个符合条件的元素的索引
const index = users.findIndex(u => u.age > 26);
console.log(index);  // 1

some 和 every

const numbers = [1, 2, 3, 4, 5];

// 检查是否有元素满足条件
const hasEven = numbers.some(num => num % 2 === 0);
console.log(hasEven);  // true

const hasGreaterThanTen = numbers.some(num => num > 10);
console.log(hasGreaterThanTen);  // false

// 检查是否所有元素都满足条件
const allPositive = numbers.every(num => num > 0);
console.log(allPositive);  // true

const allLessThanTen = numbers.every(num => num < 10);
console.log(allLessThanTen);  // true

数组高级操作

const fruits = ['苹果', '香蕉', '橙子', '葡萄', '草莓'];

// 数组拼接
const moreFruits = ['西瓜', '芒果'];
const allFruits = fruits.concat(moreFruits);
console.log(allFruits);  // ['苹果', '香蕉', '橙子', '葡萄', '草莓', '西瓜', '芒果']

// 数组切片
const firstThree = fruits.slice(0, 3);
console.log(firstThree);  // ['苹果', '香蕉', '橙子']

const lastTwo = fruits.slice(-2);
console.log(lastTwo);  // ['葡萄', '草莓']

// 数组排序
const numbers = [3, 1, 4, 1, 5, 9, 2, 6];
numbers.sort((a, b) => a - b);
console.log(numbers);  // [1, 1, 2, 3, 4, 5, 6, 9]

// 数组反转
const reversed = fruits.reverse();
console.log(reversed);  // ['草莓', '葡萄', '橙子', '香蕉', '苹果']

// 数组去重
const uniqueNumbers = [1, 2, 2, 3, 3, 3, 4];
const unique = [...new Set(uniqueNumbers)];
console.log(unique);  // [1, 2, 3, 4]

// 数组展平
const nested = [[1, 2], [3, 4], [5, 6]];
const flattened = nested.flat();
console.log(flattened);  // [1, 2, 3, 4, 5, 6]

// 数组填充
const filled = new Array(5).fill(0);
console.log(filled);  // [0, 0, 0, 0, 0]

对象基础

对象是键值对的集合,用于存储相关数据。

// 创建对象
const person = {
  name: '张三',
  age: 25,
  city: '北京',
  isStudent: false
};

// 访问对象属性
console.log(person.name);      // 张三(点表示法)
console.log(person['age']);   // 25(括号表示法)

// 添加属性
person.email = 'zhangsan@example.com';
console.log(person.email);  // zhangsan@example.com

// 修改属性
person.age = 26;
console.log(person.age);  // 26

// 删除属性
delete person.isStudent;
console.log(person.isStudent);  // undefined

// 检查属性是否存在
console.log('name' in person);    // true
console.log('isStudent' in person);  // false

// 获取所有键
console.log(Object.keys(person));  // ['name', 'age', 'city', 'email']

// 获取所有值
console.log(Object.values(person));  // ['张三', 26, '北京', 'zhangsan@example.com']

// 获取所有键值对
console.log(Object.entries(person));  // [['name', '张三'], ['age', 26], ['city', '北京'], ['email', 'zhangsan@example.com']]

对象方法

const user = {
  name: '张三',
  age: 25,
  email: 'zhangsan@example.com',
  
  // 对象方法
  greet: function() {
    return `你好,我是 ${this.name}`;
  },
  
  // 箭头函数方法(注意 this 指向)
  getInfo: () => {
    return `用户信息:${user.name},${user.age}岁`;
  },
  
  // 更新年龄
  updateAge: function(newAge) {
    this.age = newAge;
    return `年龄已更新为 ${newAge}`;
  }
};

console.log(user.greet());  // 你好,我是 张三
console.log(user.getInfo());  // 用户信息:张三,25岁
console.log(user.updateAge(26));  // 年龄已更新为 26
console.log(user.age);  // 26

对象解构

解构赋值让我们能够从对象中提取属性并赋值给变量。

const person = {
  name: '张三',
  age: 25,
  city: '北京',
  email: 'zhangsan@example.com'
};

// 基本解构
const { name, age } = person;
console.log(name);  // 张三
console.log(age);   // 25

// 重命名解构
const { name: userName, age: userAge } = person;
console.log(userName);  // 张三
console.log(userAge);   // 25

// 默认值解构
const { name, country = '中国' } = person;
console.log(name);     // 张三
console.log(country);  // 中国(person 中没有 country 属性)

// 嵌套解构
const user = {
  name: '张三',
  address: {
    city: '北京',
    district: '朝阳区',
    street: '建国路'
  }
};

const { name, address: { city, district } } = user;
console.log(name);     // 张三
console.log(city);     // 北京
console.log(district);  // 朝阳区

数组解构

const colors = ['红色', '绿色', '蓝色'];

// 基本解构
const [first, second, third] = colors;
console.log(first);   // 红色
console.log(second);  // 绿色
console.log(third);   // 蓝色

// 忽略某些元素
const [first, , third] = colors;
console.log(first);  // 红色
console.log(third);  // 蓝色

// 使用剩余元素
const [first, ...rest] = colors;
console.log(first);  // 红色
console.log(rest);   // ['绿色', '蓝色']

// 默认值
const [primary, secondary = '白色'] = colors;
console.log(primary);    // 红色
console.log(secondary);  // 绿色

// 交换变量
let a = 1;
let b = 2;
[a, b] = [b, a];
console.log(a);  // 2
console.log(b);  // 1

对象与数组的转换

// 对象转数组
const person = {
  name: '张三',
  age: 25,
  city: '北京'
};

// 使用 Object.entries
const personArray = Object.entries(person);
console.log(personArray);  // [['name', '张三'], ['age', 25], ['city', '北京']]

// 使用 Object.keys
const keys = Object.keys(person);
console.log(keys);  // ['name', 'age', 'city']

// 使用 Object.values
const values = Object.values(person);
console.log(values);  // ['张三', 25, '北京']

// 数组转对象
const users = [
  { id: 1, name: '张三' },
  { id: 2, name: '李四' },
  { id: 3, name: '王五' }
];

const usersObject = users.reduce((acc, user) => {
  acc[user.id] = user;
  return acc;
}, {});

console.log(usersObject);
// {
//   '1': { id: 1, name: '张三' },
//   '2': { id: 2, name: '李四' },
//   '3': { id: 3, name: '王五' }
// }

实用案例分析

案例 1:购物车系统

创建一个简单的购物车系统,管理商品和价格。

class ShoppingCart {
  constructor() {
    this.items = [];
  }
  
  // 添加商品
  addItem(product) {
    const existingItem = this.items.find(item => item.id === product.id);
    
    if (existingItem) {
      existingItem.quantity += product.quantity;
    } else {
      this.items.push({
        ...product,
        quantity: product.quantity || 1
      });
    }
  }
  
  // 移除商品
  removeItem(productId) {
    this.items = this.items.filter(item => item.id !== productId);
  }
  
  // 更新商品数量
  updateQuantity(productId, quantity) {
    const item = this.items.find(item => item.id === productId);
    if (item) {
      if (quantity <= 0) {
        this.removeItem(productId);
      } else {
        item.quantity = quantity;
      }
    }
  }
  
  // 计算总价
  getTotalPrice() {
    return this.items.reduce((total, item) => {
      return total + (item.price * item.quantity);
    }, 0);
  }
  
  // 获取商品总数
  getTotalItems() {
    return this.items.reduce((total, item) => {
      return total + item.quantity;
    }, 0);
  }
  
  // 清空购物车
  clear() {
    this.items = [];
  }
  
  // 获取购物车信息
  getSummary() {
    return {
      items: this.items,
      totalItems: this.getTotalItems(),
      totalPrice: this.getTotalPrice()
    };
  }
}

// 使用示例
const cart = new ShoppingCart();

// 添加商品
cart.addItem({ id: 1, name: 'iPhone 13', price: 6999, quantity: 1 });
cart.addItem({ id: 2, name: 'AirPods Pro', price: 1999, quantity: 2 });
cart.addItem({ id: 3, name: '充电器', price: 149, quantity: 1 });

console.log('购物车信息:');
console.log(cart.getSummary());

// 添加已存在的商品(增加数量)
cart.addItem({ id: 1, name: 'iPhone 13', price: 6999, quantity: 1 });
console.log('\n添加更多 iPhone 后:');
console.log(cart.getSummary());

// 更新商品数量
cart.updateQuantity(2, 1);
console.log('\n更新 AirPods 数量后:');
console.log(cart.getSummary());

// 移除商品
cart.removeItem(3);
console.log('\n移除充电器后:');
console.log(cart.getSummary());

案例 2:用户管理系统

创建一个用户管理系统,支持增删改查操作。

class UserManager {
  constructor() {
    this.users = [];
    this.nextId = 1;
  }
  
  // 添加用户
  addUser(userData) {
    const user = {
      id: this.nextId++,
      ...userData,
      createdAt: new Date(),
      updatedAt: new Date()
    };
    
    this.users.push(user);
    return user;
  }
  
  // 获取用户
  getUser(id) {
    return this.users.find(user => user.id === id);
  }
  
  // 更新用户
  updateUser(id, updates) {
    const index = this.users.findIndex(user => user.id === id);
    
    if (index !== -1) {
      this.users[index] = {
        ...this.users[index],
        ...updates,
        updatedAt: new Date()
      };
      return this.users[index];
    }
    
    return null;
  }
  
  // 删除用户
  deleteUser(id) {
    const index = this.users.findIndex(user => user.id === id);
    
    if (index !== -1) {
      const deleted = this.users.splice(index, 1)[0];
      return deleted;
    }
    
    return null;
  }
  
  // 获取所有用户
  getAllUsers() {
    return this.users;
  }
  
  // 搜索用户
  searchUsers(keyword) {
    const lowerKeyword = keyword.toLowerCase();
    return this.users.filter(user => 
      user.name.toLowerCase().includes(lowerKeyword) ||
      user.email.toLowerCase().includes(lowerKeyword)
    );
  }
  
  // 按条件筛选用户
  filterUsers(condition) {
    return this.users.filter(condition);
  }
  
  // 获取用户统计
  getStats() {
    return {
      totalUsers: this.users.length,
      activeUsers: this.users.filter(user => user.isActive).length,
      averageAge: this.calculateAverageAge()
    };
  }
  
  // 计算平均年龄
  calculateAverageAge() {
    if (this.users.length === 0) return 0;
    
    const totalAge = this.users.reduce((sum, user) => sum + user.age, 0);
    return totalAge / this.users.length;
  }
}

// 使用示例
const userManager = new UserManager();

// 添加用户
userManager.addUser({
  name: '张三',
  email: 'zhangsan@example.com',
  age: 25,
  isActive: true
});

userManager.addUser({
  name: '李四',
  email: 'lisi@example.com',
  age: 30,
  isActive: true
});

userManager.addUser({
  name: '王五',
  email: 'wangwu@example.com',
  age: 28,
  isActive: false
});

console.log('所有用户:');
console.log(userManager.getAllUsers());

// 获取用户
const user = userManager.getUser(1);
console.log('\n获取用户 ID 1:');
console.log(user);

// 更新用户
console.log('\n更新用户 ID 1:');
const updated = userManager.updateUser(1, { age: 26, city: '北京' });
console.log(updated);

// 搜索用户
console.log('\n搜索包含"张"的用户:');
const searchResults = userManager.searchUsers('张');
console.log(searchResults);

// 筛选活跃用户
console.log('\n活跃用户:');
const activeUsers = userManager.filterUsers(user => user.isActive);
console.log(activeUsers);

// 获取统计信息
console.log('\n用户统计:');
console.log(userManager.getStats());

// 删除用户
console.log('\n删除用户 ID 3:');
const deleted = userManager.deleteUser(3);
console.log(deleted);

案例 3:数据分析工具

创建一个数据分析工具,处理和分析数组数据。

class DataAnalyzer {
  constructor(data) {
    this.data = data;
  }
  
  // 计算平均值
  average() {
    if (this.data.length === 0) return 0;
    const sum = this.data.reduce((acc, val) => acc + val, 0);
    return sum / this.data.length;
  }
  
  // 计算中位数
  median() {
    if (this.data.length === 0) return 0;
    
    const sorted = [...this.data].sort((a, b) => a - b);
    const mid = Math.floor(sorted.length / 2);
    
    if (sorted.length % 2 === 0) {
      return (sorted[mid - 1] + sorted[mid]) / 2;
    } else {
      return sorted[mid];
    }
  }
  
  // 计算众数
  mode() {
    if (this.data.length === 0) return 0;
    
    const frequency = {};
    let maxFreq = 0;
    let modes = [];
    
    this.data.forEach(value => {
      frequency[value] = (frequency[value] || 0) + 1;
      if (frequency[value] > maxFreq) {
        maxFreq = frequency[value];
      }
    });
    
    for (const value in frequency) {
      if (frequency[value] === maxFreq) {
        modes.push(Number(value));
      }
    }
    
    return modes.length === 1 ? modes[0] : modes;
  }
  
  // 计算标准差
  standardDeviation() {
    if (this.data.length === 0) return 0;
    
    const avg = this.average();
    const squareDiffs = this.data.map(value => Math.pow(value - avg, 2));
    const avgSquareDiff = squareDiffs.reduce((acc, val) => acc + val, 0) / this.data.length;
    
    return Math.sqrt(avgSquareDiff);
  }
  
  // 计算范围
  range() {
    if (this.data.length === 0) return { min: 0, max: 0, range: 0 };
    
    const min = Math.min(...this.data);
    const max = Math.max(...this.data);
    
    return {
      min,
      max,
      range: max - min
    };
  }
  
  // 分组统计
  groupBy(groupSize) {
    const groups = [];
    
    for (let i = 0; i < this.data.length; i += groupSize) {
      groups.push(this.data.slice(i, i + groupSize));
    }
    
    return groups;
  }
  
  // 频率分布
  frequencyDistribution() {
    const distribution = {};
    
    this.data.forEach(value => {
      distribution[value] = (distribution[value] || 0) + 1;
    });
    
    return distribution;
  }
  
  // 百分位数
  percentile(percentile) {
    if (this.data.length === 0) return 0;
    
    const sorted = [...this.data].sort((a, b) => a - b);
    const index = Math.ceil((percentile / 100) * sorted.length) - 1;
    
    return sorted[index];
  }
  
  // 生成完整报告
  generateReport() {
    return {
      count: this.data.length,
      average: this.average(),
      median: this.median(),
      mode: this.mode(),
      standardDeviation: this.standardDeviation(),
      range: this.range(),
      percentile25: this.percentile(25),
      percentile50: this.percentile(50),
      percentile75: this.percentile(75),
      percentile90: this.percentile(90),
      frequencyDistribution: this.frequencyDistribution()
    };
  }
}

// 使用示例
const scores = [85, 92, 78, 95, 88, 76, 90, 82, 87, 91, 79];
const analyzer = new DataAnalyzer(scores);

console.log('数据分析报告:');
console.log(analyzer.generateReport());

// 分组统计
console.log('\n分组统计(每组 3 个):');
const groups = analyzer.groupBy(3);
console.log(groups);

// 频率分布
console.log('\n频率分布:');
const distribution = analyzer.frequencyDistribution();
console.log(distribution);

代码示例

示例 1:数组方法链式调用

const products = [
  { name: 'iPhone 13', price: 6999, category: '手机', inStock: true },
  { name: 'MacBook Pro', price: 14999, category: '电脑', inStock: true },
  { name: 'AirPods Pro', price: 1999, category: '耳机', inStock: false },
  { name: 'iPad Pro', price: 6199, category: '平板', inStock: true },
  { name: 'Apple Watch', price: 2999, category: '手表', inStock: true }
];

// 链式调用:筛选、映射、排序
const result = products
  .filter(product => product.inStock && product.price < 10000)
  .map(product => ({
    name: product.name,
    category: product.category,
    discountedPrice: product.price * 0.9
  }))
  .sort((a, b) => a.discountedPrice - b.discountedPrice);

console.log('筛选和排序后的商品:');
console.log(result);

// 统计每个分类的商品数量
const categoryCount = products
  .reduce((acc, product) => {
    acc[product.category] = (acc[product.category] || 0) + 1;
    return acc;
  }, {});

console.log('\n分类统计:');
console.log(categoryCount);

示例 2:对象深拷贝与合并

// 浅拷贝问题
const original = {
  name: '张三',
  age: 25,
  address: {
    city: '北京',
    district: '朝阳区'
  }
};

const shallowCopy = { ...original };
shallowCopy.address.city = '上海';

console.log('原始对象:');
console.log(original.address.city);  // 上海(被修改了!)

// 深拷贝方法 1:使用 JSON
const deepCopy1 = JSON.parse(JSON.stringify(original));
deepCopy1.address.city = '广州';

console.log('\n深拷贝后:');
console.log(original.address.city);  // 上海(未被修改)
console.log(deepCopy1.address.city);  // 广州

// 深拷贝方法 2:使用递归
function deepClone(obj) {
  if (obj === null || typeof obj !== 'object') {
    return obj;
  }
  
  if (Array.isArray(obj)) {
    return obj.map(item => deepClone(item));
  }
  
  const cloned = {};
  for (const key in obj) {
    if (obj.hasOwnProperty(key)) {
      cloned[key] = deepClone(obj[key]);
    }
  }
  
  return cloned;
}

const deepCopy2 = deepClone(original);
deepCopy2.address.district = '海淀区';

console.log('\n递归深拷贝后:');
console.log(original.address.district);  // 朝阳区(未被修改)
console.log(deepCopy2.address.district);  // 海淀区

// 对象合并
const defaults = {
  theme: 'light',
  language: 'zh-CN',
  fontSize: 14
};

const userSettings = {
  language: 'en-US',
  fontSize: 16
};

const mergedSettings = { ...defaults, ...userSettings };
console.log('\n合并后的设置:');
console.log(mergedSettings);  // { theme: 'light', language: 'en-US', fontSize: 16 }

示例 3:数组与对象的高级操作

// 数组去重并保持顺序
function uniqueArray(array) {
  const seen = new Set();
  return array.filter(item => {
    if (seen.has(item)) {
      return false;
    }
    seen.add(item);
    return true;
  });
}

const numbers = [1, 2, 2, 3, 3, 3, 4, 5, 5];
console.log('去重后的数组:');
console.log(uniqueArray(numbers));  // [1, 2, 3, 4, 5]

// 数组分组
function groupBy(array, key) {
  return array.reduce((groups, item) => {
    const groupKey = item[key];
    if (!groups[groupKey]) {
      groups[groupKey] = [];
    }
    groups[groupKey].push(item);
    return groups;
  }, {});
}

const users = [
  { name: '张三', department: '技术部' },
  { name: '李四', department: '市场部' },
  { name: '王五', department: '技术部' },
  { name: '赵六', department: '市场部' }
];

console.log('\n按部门分组:');
console.log(groupBy(users, 'department'));

// 对象路径访问
function getValueByPath(obj, path) {
  return path.split('.').reduce((current, key) => {
    return current && current[key] !== undefined ? current[key] : undefined;
  }, obj);
}

const data = {
  user: {
    profile: {
      name: '张三',
      contact: {
        email: 'zhangsan@example.com',
        phone: '1234567890'
      }
    }
  }
};

console.log('\n路径访问:');
console.log(getValueByPath(data, 'user.profile.name'));  // 张三
console.log(getValueByPath(data, 'user.profile.contact.email'));  // zhangsan@example.com

// 数组交集、并集、差集
const array1 = [1, 2, 3, 4, 5];
const array2 = [3, 4, 5, 6, 7];

const intersection = array1.filter(x => array2.includes(x));
const union = [...new Set([...array1, ...array2])];
const difference = array1.filter(x => !array2.includes(x));

console.log('\n数组操作:');
console.log('交集:', intersection);  // [3, 4, 5]
console.log('并集:', union);  // [1, 2, 3, 4, 5, 6, 7]
console.log('差集:', difference);  // [1, 2]

实现技巧与注意事项

数组操作最佳实践

  1. 使用适当的方法:根据需求选择合适的数组方法
  2. 避免修改原数组:使用 map、filter 等方法返回新数组
  3. 考虑性能:大数组操作时注意性能影响
  4. 使用解构:提高代码可读性

对象操作最佳实践

  1. 使用 const 声明对象:避免意外重新赋值
  2. 使用解构赋值:提取需要的属性
  3. 深拷贝时注意性能:大对象深拷贝可能影响性能
  4. 使用 Object.freeze:防止对象被意外修改

性能优化建议

  1. 避免在循环中创建函数:提前定义函数
  2. 使用 for 循环处理大数组:比 forEach 性能更好
  3. 使用 Set 进行快速查找:比 Array.includes 性能更好
  4. 使用 Map 替代对象:当键不是字符串时

常见问题与解决方案

问题 1:数组方法修改原数组

// 问题代码
const original = [1, 2, 3, 4, 5];
const reversed = original.reverse();
console.log(original);  // [5, 4, 3, 2, 1](原数组被修改)

// 解决方案
const original = [1, 2, 3, 4, 5];
const reversed = [...original].reverse();
console.log(original);  // [1, 2, 3, 4, 5](原数组未被修改)
console.log(reversed);  // [5, 4, 3, 2, 1]

问题 2:对象引用问题

// 问题代码
const original = { name: '张三', age: 25 };
const copy = original;
copy.age = 26;
console.log(original.age);  // 26(原对象被修改)

// 解决方案
const original = { name: '张三', age: 25 };
const copy = { ...original };
copy.age = 26;
console.log(original.age);  // 25(原对象未被修改)
console.log(copy.age);  // 26

问题 3:数组遍历中的异步操作

// 问题代码
const urls = ['url1', 'url2', 'url3'];
const results = [];

urls.forEach(async (url) => {
  const data = await fetchData(url);
  results.push(data);
});

console.log(results);  // [](forEach 不等待异步操作完成)

// 解决方案 1:使用 for...of
const urls = ['url1', 'url2', 'url3'];
const results = [];

for (const url of urls) {
  const data = await fetchData(url);
  results.push(data);
}

console.log(results);  // [data1, data2, data3]

// 解决方案 2:使用 Promise.all
const urls = ['url1', 'url2', 'url3'];
const results = await Promise.all(urls.map(url => fetchData(url)));
console.log(results);  // [data1, data2, data3]

问题 4:对象属性检查

// 问题代码
const obj = { name: '张三', age: 25 };
if (obj.city) {  // 如果 city 是 0 或空字符串,会误判
  console.log('有城市信息');
}

// 解决方案
const obj = { name: '张三', age: 25 };
if ('city' in obj) {  // 正确检查属性是否存在
  console.log('有城市信息');
}

if (obj.city !== undefined) {  // 另一种检查方式
  console.log('有城市信息');
}

总结

本教程详细介绍了 JavaScript 数组和对象的操作方法,包括数组遍历、对象属性访问、解构赋值等核心知识点。这些技能对于处理复杂数据结构至关重要。

通过本集的学习,您应该能够:

  1. 熟练使用数组的各种方法
  2. 理解对象的基本操作和高级特性
  3. 掌握解构赋值的使用技巧
  4. 能够进行数组与对象的相互转换
  5. 处理实际的数据分析和管理任务
  6. 避免常见的数组对象操作错误

在下一集中,我们将学习 JavaScript ES6+ 新特性,这将大大提升您的编程效率和代码质量。继续加油,您的 JavaScript 技能正在不断提升!

« 上一篇 JavaScript 函数与作用域 下一篇 » JavaScript ES6+ 新特性