如何获取JSON对象的所有Key:全面指南
在JavaScript开发中,JSON(JavaScript Object Notation)作为一种轻量级的数据交换格式,被广泛应用于前后端数据交互,操作JSON对象时,获取其所有的键(Key)是一项基础且高频的需求——无论是遍历数据、动态渲染界面,还是进行数据校验,都离不开对Key的精准获取,本文将详细介绍在不同场景下获取JSON对象所有Key的方法,从基础操作到进阶技巧,助你彻底这一技能。
理解JSON对象与JavaScript对象的关系
在开始之前,需要明确一个核心概念:JSON对象本质上是JavaScript对象的一种规范表示,在实际开发中,我们常说的“JSON对象”通常是指符合JSON语法的JavaScript对象(如{ "name": "张三", "age": 18 }),而非服务器返回的原始JSON字符串(需通过JSON.parse()解析为JavaScript对象)。
获取JSON对象的Key,本质上是获取JavaScript对象的可枚举属性(Enumerable Properties),基于这一点,JavaScript原生提供了多种方法来遍历和获取对象的Key。
核心方法:Object.keys()与Object.getOwnPropertyNames()
Object.keys():获取可枚举的自有属性
Object.keys()是JavaScript中专门用于获取对象可枚举自有属性(Own Enumerable Properties)的静态方法,所谓“自有属性”,指直接定义在对象本身(而非通过原型链继承)的属性;“可枚举”则表示该属性会被for...in循环遍历到(默认情况下,对象属性都是可枚举的,除非通过Object.defineProperty()设置为enumerable: false)。
语法
Object.keys(obj)
- 参数obj:要获取Key的对象。
- 返回值:一个数组,包含对象所有可枚举的自有属性的Key(顺序与for...in循环一致,即属性定义时的数字索引升序、字符串插入顺序)。
示例
const user = {
  name: "李四",
  age: 25,
  occupation: "工程师"
};
const keys = Object.keys(user);
console.log(keys); // 输出: ["name", "age", "occupation"]
注意事项
- 仅返回自有属性:如果对象有通过原型链继承的属性(如toString、hasOwnProperty等),Object.keys()不会包含它们。
- 忽略不可枚举属性:如果属性被设置为不可枚举,则不会出现在结果中。
const obj = { a: 1 };
Object.defineProperty(obj, "b", {
  value: 2,
  enumerable: false // 设置为不可枚举
});
console.log(Object.keys(obj)); // 输出: ["a"]("b"被忽略)
Object.getOwnPropertyNames():获取所有自有属性(含不可枚举)
如果需要获取对象所有自有属性(包括可枚举和不可枚举的),可以使用Object.getOwnPropertyNames(),它与Object.keys()的核心区别在于:不区分属性的可枚举性,只要属性是对象自有的,就会被包含在结果中。
语法
Object.getOwnPropertyNames(obj)
- 参数obj:要获取Key的对象。
- 返回值:一个数组,包含对象所有自有属性的Key(顺序与属性定义时的顺序一致)。
示例
const obj = { a: 1 };
Object.defineProperty(obj, "b", {
  value: 2,
  enumerable: false // 不可枚举属性
});
console.log(Object.getOwnPropertyNames(obj)); // 输出: ["a", "b"](包含不可枚举的"b")
与Object.keys()的对比
| 方法 | 返回属性范围 | 是否包含不可枚举属性 | 是否包含继承属性 | 
|---|---|---|---|
| Object.keys() | 可枚举的自有属性 | 否 | 否 | 
| Object.getOwnPropertyNames() | 所有自有属性 | 是 | 否 | 
进阶场景:处理嵌套JSON对象与Symbol属性
获取嵌套JSON对象的所有Key
实际开发中,JSON对象往往是嵌套的(如{ user: { name: "王五" }, hobbies: ["reading"] }),若要获取所有层级的Key(包括嵌套对象的Key),需要递归遍历对象。
递归获取所有Key的函数
function getAllKeys(obj, parentKey = "", result = []) {
  if (typeof obj !== "object" || obj === null) {
    return result; // 基本类型或null,直接返回
  }
  Object.keys(obj).forEach(key => {
    const fullKey = parentKey ? `${parentKey}.${key}` : key; // 构建层级Key(如"user.name")
    result.push(fullKey);
    // 如果当前属性的值是对象且不是数组,则递归处理
    if (typeof obj[key] === "object" && obj[key] !== null && !Array.isArray(obj[key])) {
      getAllKeys(obj[key], fullKey, result);
    }
  });
  return result;
}
const nestedObj = {
  user: {
    name: "王五",
    contact: {
      email: "wangwu@example.com"
    }
  },
  hobbies: ["reading", "coding"]
};
console.log(getAllKeys(nestedObj));
// 输出: ["user", "user.name", "user.contact", "user.contact.email", "hobbies"]
说明
- 通过parentKey参数记录父级Key,构建层级路径(如user.contact.email)。
- 递归终止条件:当属性值为基本类型(非对象)或null时停止递归。
- 数组(Array)被视为特殊对象,但通常我们不希望展开数组的索引作为Key(如hobbies.0),因此通过!Array.isArray(obj[key])排除数组。
处理Symbol属性
JavaScript中,除了字符串类型的属性Key,还支持Symbol类型的Key(唯一且不可变)。Object.keys()和Object.getOwnPropertyNames()均无法获取Symbol属性,需使用Object.getOwnPropertySymbols()方法。
获取Symbol属性的Key
const sym1 = Symbol("id");
const sym2 = Symbol("type");
const obj = {
  name: "赵六",
  [sym1]: 123, // Symbol属性
  [sym2]: "admin"
};
// 获取字符串Key
console.log(Object.keys(obj)); // 输出: ["name"]
// 获取Symbol Key
console.log(Object.getOwnPropertySymbols(obj)); // 输出: [Symbol(id), Symbol(type)]
获取所有属性(字符串+Symbol)
如果需要获取对象的所有Key(包括字符串和Symbol类型),可以结合Object.keys()和Object.getOwnPropertySymbols():
const allKeys = [...Object.keys(obj), ...Object.getOwnPropertySymbols(obj)]; console.log(allKeys); // 输出: ["name", Symbol(id), Symbol(type)]
特殊场景:数组、类数组和null/undefined
数组(Array)的Key
数组在JavaScript中是一种特殊的对象,其元素本质上是对象的数字索引属性(0、1、2...)。Object.keys()会返回数组的索引:
const arr = ["apple", "banana", "cherry"]; console.log(Object.keys(arr)); // 输出: ["0", "1", "2"]
但通常我们更关心数组的元素而非索引,因此直接遍历数组(for...of或forEach)更常见。
类数组(Array-like)的Key
类数组对象(如arguments、NodeList、HTMLCollection)具有数字索引和length属性,但不是真正的数组。Object.keys()同样会返回其索引:
function getArguments() {
  console.log(Object.keys(arguments)); // arguments是类数组
}
getArguments("a", "b"); // 输出: ["0", "1"]
null和undefined的Key
null和undefined是基本类型,不是对象,因此无法直接调用Object.keys()等方法,否则会抛出TypeError:
console.log(Object.keys(null)); // 报错: TypeError: Object.keys called on non-object console.log(Object.keys(undefined)); // 报错: TypeError: Object.keys called on non-object
解决方案:调用前先检查类型:
const objOrNull = null; const keys = objOrNull && typeof objOrNull === "object" ? Object.keys(objOrNull) : []; console.log(keys); // 输出: []
性能对比与最佳实践
方法性能对比
在大多数现代JavaScript引擎中:
- Object.keys()的性能优于- Object.getOwnPropertyNames(),因为它只需遍历可枚举属性,无需检查不可枚举属性。
- 递归遍历嵌套对象时,性能会随对象深度和宽度增加




 
		 
		 
		 
		
还没有评论,来说两句吧...