文章目录

JavaScript 对象操作:Object.keys() 与 Object.values()

发布于 2026-04-06 00:55:56 · 浏览 10 次 · 评论 0 条

JavaScript 对象操作:Object.keys() 与 Object.values()

在 JavaScript 开发中,对象是最常用的数据结构之一。当我们需要遍历对象属性、过滤数据或进行数据转换时,Object.keys()Object.values() 是两个高频使用的方法。这两个方法专门用于获取对象的键名集合和属性值集合,配合数组方法使用,能大幅简化对象处理逻辑。

本文将系统讲解这两个方法的用法、适用场景以及实际开发中的最佳实践。


Object.keys():获取对象的所有键名

方法概述

Object.keys() 返回一个数组,包含对象自身的所有可枚举属性的键名(不含继承的属性)。语法如下:

Object.keys(obj)

其中 obj 是目标对象,返回值是一个字符串数组。

基本用法

const user = {
  name: '张三',
  age: 28,
  city: '北京'
};

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

典型应用场景

1. 遍历对象的所有属性

const config = {
  apiUrl: 'https://api.example.com',
  timeout: 5000,
  retries: 3
};

Object.keys(config).forEach(key => {
  console.log(`${key}: ${config[key]}`);
});

输出结果:

apiUrl: https://api.example.com
timeout: 5000
retries: 3

2. 过滤对象的某些属性

const product = {
  id: 1001,
  name: '笔记本电脑',
  price: 5999,
  stock: 50,
  category: '电子产品'
};

// 只获取以 'p' 开头的属性
const pKeys = Object.keys(product).filter(key => key.startsWith('p'));
console.log(pKeys); // ['price', 'product']

3. 将对象转为 Map 结构

const settings = {
  theme: 'dark',
  language: 'zh-CN',
  notifications: true
};

const settingsMap = new Map(
  Object.keys(settings).map(key => [key, settings[key]])
);

Object.values():获取对象的所有属性值

方法概述

Object.values() 返回一个数组,包含对象自身的所有可枚举属性的值。与 Object.keys() 对应,语法如下:

Object.values(obj)

基本用法

const book = {
  title: 'JavaScript高级程序设计',
  author: 'Nicholas C. Zakas',
  pages: 724,
  price: 89.00
};

const values = Object.values(book);
console.log(values); 
// ['JavaScript高级程序设计', 'Nicholas C. Zakas', 724, 89]

典型应用场景

1. 快速获取所有值进行计算

const scores = {
  math: 85,
  english: 92,
  chinese: 78,
  science: 88
};

// 计算平均分
const total = Object.values(scores).reduce((sum, val) => sum + val, 0);
const average = total / Object.values(scores).length;
console.log(`总分: ${total}, 平均分: ${average.toFixed(2)}`);
// 总分: 343, 平均分: 85.75

2. 只关心值不在乎键名的场景

const weekdays = {
  0: '周日',
  1: '周一',
  2: '周二',
  3: '周三',
  4: '周四',
  5: '周五',
  6: '周六'
};

// 获取工作日列表
const workDays = Object.values(weekdays).filter(day => !day.includes('周'));
// ['周一', '周二', '周三', '周四', '周五']

3. 提取特定类型的值

const formData = {
  username: 'john_doe',
  email: 'john@example.com',
  age: '30',
  isAdmin: 'false'
};

// 提取所有字符串类型的值
const stringValues = Object.values(formData).filter(val => typeof val === 'string');

两者配合使用

同步获取键和值

当需要同时使用键名和属性值时,可以将 Object.keys()Object.values() 结合数组的索引对应关系:

const employee = {
  department: '技术部',
  position: '高级工程师',
  salary: 25000,
  joinDate: '2021-03-15'
};

const keys = Object.keys(employee);
const values = Object.values(employee);

keys.forEach((key, index) => {
  console.log(`${key} -> ${values[index]}`);
});

更优雅的写法是使用 Object.entries(),本文会在后文详细说明。

深度对象处理

const nested = {
  level1: {
    level2a: 'value1',
    level2b: 'value2'
  },
  level1c: 'value3'
};

// 获取第一层所有值
const firstLevelValues = Object.values(nested);
// [{ level2a: 'value1', level2b: 'value2' }, 'value3']

// 获取第二层所有键
if (typeof firstLevelValues[0] === 'object') {
  const secondLevelKeys = Object.keys(firstLevelValues[0]);
  // ['level2a', 'level2b']
}

常见问题与注意事项

1. 只会获取自身属性

这两个方法都只返回对象自身的属性,不包含原型链上的属性:

const parent = { a: 1 };
const child = Object.create(parent);
child.b = 2;

console.log(Object.keys(child));  // ['b'] (不会包含 a)
console.log(Object.values(child)); // [2] (不会包含 1)

2. 只获取可枚举属性

通过 Object.defineProperty 添加的不可枚举属性不会被返回:

const obj = { x: 1 };
Object.defineProperty(obj, 'y', {
  value: 2,
  enumerable: false
});

console.log(Object.keys(obj));   // ['x'] (y 被省略)
console.log(Object.values(obj)); // [1] (y 被省略)

3. 数组也是对象

数组是特殊的对象,索引就是键名:

const arr = ['苹果', '香蕉', '橙子'];

console.log(Object.keys(arr));   // ['0', '1', '2']
console.log(Object.values(arr)); // ['苹果', '香蕉', '橙子']

4. Symbol 属性不会被获取

默认情况下,这两个方法不会返回 Symbol 类型的键:

const symKey = Symbol('description');
const obj = {
  regularKey: '值',
  [symKey]: 'Symbol键的值'
};

console.log(Object.keys(obj));   // ['regularKey']
console.log(Object.values(obj)); // ['值']

如需获取 Symbol 属性,使用 Object.getOwnPropertySymbols()


性能考量

大型对象的处理

对于包含大量属性的对象,每次调用 Object.keys()Object.values() 都会遍历整个对象。如果需要多次使用,建议将结果缓存:

const largeObject = { /* 大量属性 */ };

// 不推荐:每次调用都会遍历
for (let i = 0; i < 1000; i++) {
  Object.keys(largeObject).forEach(key => process(key));
}

// 推荐:缓存结果
const keys = Object.keys(largeObject);
for (let i = 0; i < 1000; i++) {
  keys.forEach(key => process(key));
}

与 Object.entries() 的选择

如果同时需要键和值,使用 Object.entries() 更加高效:

const obj = { a: 1, b: 2, c: 3 };

// 低效:两次遍历
Object.keys(obj).forEach(key => {
  console.log(`${key}: ${obj[key]}`);
});

// 高效:一次遍历
Object.entries(obj).forEach(([key, value]) => {
  console.log(`${key}: ${value}`);
});

方法对比速查表

特性 Object.keys() Object.values()
返回内容 键名字符串数组 属性值数组
返回类型 string[] (string\|number\|boolean\|object)[]
适用场景 需要操作键名时 需要处理属性值时
与 entries() 配合 需要自行映射 需要自行映射

最佳实践建议

1. 优先使用解构获取特定属性

const config = { host: 'localhost', port: 8080, secure: false };

// 推荐:直接解构需要的属性
const { host, port } = config;

2. 结合数组方法链式操作

const data = { a: 10, b: 20, c: 30, d: 40 };

// 过滤出值大于 15 的项
const filtered = Object.entries(data)
  .filter(([key, value]) => value > 15)
  .reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {});

3. 对象转数组的常见模式

const users = {
  user1: { name: 'Alice' },
  user2: { name: 'Bob' },
  user3: { name: 'Charlie' }
};

// 获取所有用户名
const names = Object.values(users).map(user => user.name);
// ['Alice', 'Bob', 'Charlie']

掌握 Object.keys()Object.values() 的用法,能让你在处理 JavaScript 对象时更加得心应手。建议在实际开发中多加练习,将这两个方法与数组方法灵活结合,可以大幅提升代码的可读性和开发效率。

评论 (0)

暂无评论,快来抢沙发吧!

扫一扫,手机查看

扫描上方二维码,在手机上查看本文