JS `Object.keys()` / `Object.values()` / `Object.entries()` 在对象遍历中的应用

嘿,大家好!欢迎来到今天的JS对象遍历小课堂。我是你们的老朋友,今天咱们就来聊聊 Object.keys()Object.values()Object.entries() 这三个小可爱,看看它们在对象遍历中能玩出什么花样。

咱们的目标是:用最通俗易懂的方式,把这三个方法掰开了揉碎了讲清楚,让大家以后在处理对象的时候,能像指挥自己家的宠物一样,指哪打哪!

第一章:开胃小菜 – 为什么要遍历对象?

在咱们深入了解这三个方法之前,先来思考一个问题:为什么要遍历对象?

想象一下,你有一个装满了各种信息的箱子(对象),比如:

const person = {
  name: '张三',
  age: 30,
  city: '北京',
  job: '程序员'
};

如果你想知道这个箱子里都有什么东西,或者想把里面的东西拿出来整理一下,那就需要遍历这个箱子。在JavaScript的世界里,遍历对象就是为了:

  • 查看对象的所有属性和值: 就像清点家当一样,看看对象里都有哪些宝贝。
  • 修改对象的属性值: 给张三换个工作,或者搬到上海去住。
  • 基于对象的数据进行计算或操作: 比如,统计所有人的平均年龄。
  • 将对象的数据转换成其他格式: 比如,把对象转换成一个HTML表格。

总之,遍历对象是处理对象数据的基本功,掌握了它,你才能在JS的世界里自由驰骋。

第二章:主角登场 – Object.keys()Object.values()Object.entries()

现在,让咱们的主角们闪亮登场!

  • Object.keys(obj): 这个方法就像一个钥匙管理员,它会返回一个包含对象 obj 所有可枚举属性名的数组。记住,是属性名!而且返回的是字符串类型的数组。

    const person = {
      name: '张三',
      age: 30,
      city: '北京',
      job: '程序员'
    };
    
    const keys = Object.keys(person);
    console.log(keys); // 输出: ["name", "age", "city", "job"]
  • Object.values(obj): 这个方法就像一个寻宝猎人,它会返回一个包含对象 obj 所有可枚举属性值的数组。记住,是属性值!

    const person = {
      name: '张三',
      age: 30,
      city: '北京',
      job: '程序员'
    };
    
    const values = Object.values(person);
    console.log(values); // 输出: ["张三", 30, "北京", "程序员"]
  • Object.entries(obj): 这个方法就像一个打包员,它会返回一个包含对象 obj 所有可枚举属性的键值对的数组。每个键值对都是一个数组,包含两个元素:属性名和属性值。

    const person = {
      name: '张三',
      age: 30,
      city: '北京',
      job: '程序员'
    };
    
    const entries = Object.entries(person);
    console.log(entries);
    // 输出:
    // [
    //   ["name", "张三"],
    //   ["age", 30],
    //   ["city", "北京"],
    //   ["job", "程序员"]
    // ]

重点总结:

方法 返回值 作用
Object.keys() 包含对象所有可枚举属性名的数组 (字符串类型) 获取对象的所有属性名
Object.values() 包含对象所有可枚举属性值的数组 获取对象的所有属性值
Object.entries() 包含对象所有可枚举属性的键值对数组 (每个键值对都是一个数组) 获取对象的所有属性名和属性值,方便同时处理属性名和属性值

第三章:实战演练 – 如何使用它们进行遍历?

有了这三个方法,咱们就可以像玩积木一样,灵活地遍历对象了。

1. 使用 Object.keys() 遍历:

const person = {
  name: '张三',
  age: 30,
  city: '北京',
  job: '程序员'
};

const keys = Object.keys(person);

for (let i = 0; i < keys.length; i++) {
  const key = keys[i];
  const value = person[key]; // 通过属性名获取属性值
  console.log(`属性名:${key},属性值:${value}`);
}

// 输出:
// 属性名:name,属性值:张三
// 属性名:age,属性值:30
// 属性名:city,属性值:北京
// 属性名:job,属性值:程序员

或者更简洁的方式,使用 forEach:

const person = {
  name: '张三',
  age: 30,
  city: '北京',
  job: '程序员'
};

Object.keys(person).forEach(key => {
  console.log(`属性名:${key},属性值:${person[key]}`);
});

2. 使用 Object.values() 遍历:

这种方式只能访问到属性值,无法直接访问属性名。如果只需要属性值,这种方法更简洁。

const person = {
  name: '张三',
  age: 30,
  city: '北京',
  job: '程序员'
};

const values = Object.values(person);

for (let i = 0; i < values.length; i++) {
  const value = values[i];
  console.log(`属性值:${value}`);
}

// 输出:
// 属性值:张三
// 属性值:30
// 属性值:北京
// 属性值:程序员

同样可以使用 forEach:

const person = {
  name: '张三',
  age: 30,
  city: '北京',
  job: '程序员'
};

Object.values(person).forEach(value => {
  console.log(`属性值:${value}`);
});

3. 使用 Object.entries() 遍历:

这种方式可以同时访问属性名和属性值,非常方便。

const person = {
  name: '张三',
  age: 30,
  city: '北京',
  job: '程序员'
};

const entries = Object.entries(person);

for (let i = 0; i < entries.length; i++) {
  const [key, value] = entries[i]; // 使用解构赋值
  console.log(`属性名:${key},属性值:${value}`);
}

// 输出:
// 属性名:name,属性值:张三
// 属性名:age,属性值:30
// 属性名:city,属性值:北京
// 属性名:job,属性值:程序员

或者更简洁的方式,使用 forEach 和解构赋值:

const person = {
  name: '张三',
  age: 30,
  city: '北京',
  job: '程序员'
};

Object.entries(person).forEach(([key, value]) => {
  console.log(`属性名:${key},属性值:${value}`);
});

4. 结合 for...in 循环 (不推荐,但需要了解):

虽然 Object.keys()Object.values()Object.entries() 提供了更现代和更方便的遍历方式,但 for...in 循环仍然是JS中一种传统的对象遍历方式。

const person = {
  name: '张三',
  age: 30,
  city: '北京',
  job: '程序员'
};

for (const key in person) {
  if (person.hasOwnProperty(key)) { // 确保只遍历自身属性,不遍历原型链上的属性
    console.log(`属性名:${key},属性值:${person[key]}`);
  }
}

注意:

  • for...in 循环会遍历对象自身及其原型链上的所有可枚举属性。为了避免遍历到原型链上的属性,通常需要使用 hasOwnProperty() 方法进行过滤。
  • for...in 循环遍历属性的顺序是不确定的,这在某些情况下可能会导致问题。
  • 除非有特殊需求,否则建议使用 Object.keys()Object.values()Object.entries() 进行对象遍历,它们更现代、更可控。

第四章:高级技巧 – 更灵活的应用

这三个方法不仅可以用于简单的遍历,还可以结合其他JS特性,实现更复杂的功能。

1. 转换对象结构:

假设我们有一个对象,表示学生的成绩:

const scores = {
  '张三': 90,
  '李四': 85,
  '王五': 92
};

我们想把它转换成一个数组,每个元素包含学生的姓名和成绩:

const scoresArray = Object.entries(scores).map(([name, score]) => ({
  name: name,
  score: score
}));

console.log(scoresArray);
// 输出:
// [
//   { name: "张三", score: 90 },
//   { name: "李四", score: 85 },
//   { name: "王五", score: 92 }
// ]

2. 过滤对象属性:

假设我们有一个对象,包含各种配置信息:

const config = {
  apiUrl: 'https://api.example.com',
  timeout: 5000,
  debugMode: true,
  apiKey: 'YOUR_API_KEY',
  cacheEnabled: false
};

我们只想保留以 api 开头的配置项:

const apiConfig = Object.fromEntries(
  Object.entries(config).filter(([key, value]) => key.startsWith('api'))
);

console.log(apiConfig);
// 输出:
// {
//   apiUrl: "https://api.example.com",
//   apiKey: "YOUR_API_KEY"
// }

注意: 这里使用了 Object.fromEntries() 方法,它可以将一个键值对数组转换成一个对象。

3. 计算对象属性的总和:

假设我们有一个对象,表示商品的数量:

const quantities = {
  apple: 10,
  banana: 5,
  orange: 8
};

我们想计算所有商品的总数量:

const totalQuantity = Object.values(quantities).reduce((sum, quantity) => sum + quantity, 0);

console.log(totalQuantity); // 输出: 23

第五章:注意事项 – 踩坑指南

在使用 Object.keys()Object.values()Object.entries() 时,有一些坑需要注意:

  • 只遍历可枚举属性: 这三个方法只会遍历对象的可枚举属性。如果属性的 enumerable 标志被设置为 false,则不会被遍历到。

    const obj = {
      name: '张三'
    };
    
    Object.defineProperty(obj, 'age', {
      value: 30,
      enumerable: false // 不可枚举
    });
    
    console.log(Object.keys(obj)); // 输出: ["name"]
  • 遍历顺序不确定 (ES2015+ 规范): 在ES2015及以后的版本中,对于普通对象,属性的遍历顺序是按照它们被添加到对象中的顺序。但是,对于数字索引的属性(例如数组),遍历顺序是按照索引的升序排列。 尽管如此,仍然不建议依赖属性的遍历顺序,因为在不同的JS引擎中,顺序可能存在差异。

    const obj = {
      c: 3,
      a: 1,
      b: 2
    };
    
    console.log(Object.keys(obj)); // 输出: ["c", "a", "b"] (通常情况,但不保证)
    
    const arr = {
      2: 'c',
      0: 'a',
      1: 'b'
    };
    
    console.log(Object.keys(arr)); // 输出: ["0", "1", "2"] (数字索引按升序排列)
  • Object.fromEntries() 的兼容性: Object.fromEntries() 方法是ES2019新增的,在一些旧版本的浏览器中可能不支持。如果需要兼容旧版本浏览器,可以使用polyfill。

  • 避免直接修改正在遍历的对象: 在遍历对象的过程中,如果直接修改对象(例如添加、删除属性),可能会导致遍历结果不准确。

第六章:总结 – 灵活运用,事半功倍

Object.keys()Object.values()Object.entries() 是JS中非常实用的对象遍历方法。它们提供了简洁、灵活的方式来访问对象的属性名、属性值,可以帮助我们更高效地处理对象数据。

记住,选择哪个方法取决于你的具体需求:

  • 如果只需要属性名,使用 Object.keys()
  • 如果只需要属性值,使用 Object.values()
  • 如果需要同时访问属性名和属性值,使用 Object.entries()

熟练掌握这三个方法,并结合其他JS特性,你就可以在对象遍历的世界里游刃有余,写出更优雅、更高效的代码。

今天的课程就到这里,希望大家有所收获!下次再见!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注