遍历对象的所有自身属性

注:下文提到的对象指的是由字面量形式 {}new Object() 形式创建的对象。

我们的需求是:遍历出一个对象的【所有自身属性】,注意两个关键点:

  1. 所有(包括可枚举和不可枚举的属性)
  2. 自身(只包含自身属性,不考虑继承属性)

下面的代码创建了一个 obj 对象,它包含 6 个自身属性和 2 个继承属性。

js 复制代码
/**
 * 通过 Object.create() 创建 obj
 * 使其具有 x 和 y 两个继承属性
 */
const obj = Object.create( {
    x: 100,
    y: 200
} );

/**
 * 在 obj 上添加四个属性
 */
obj.a = 10;
obj.b = 20;
obj[ Symbol( "1" ) ] = 30;
obj[ Symbol( "2" ) ] = 40;

/**
 * 使用 Object.defineProperties() 再添加两个属性
 */
Object.defineProperties( obj, {
    c: {
        enumerable: true,
        value: 50
    }, 
    d: {
        enumerable: false,
        value: 60
    }
} );

理想情况下,满足需求的预期结果将返回 6 个属性,如下所示:

js 复制代码
[ 'a', 'b', 'c', 'd', Symbol(1), Symbol(2) ]

接下来我们使用四种不同的方案来遍历 obj 对象,看看哪一个符合预期。

方案一:for...in

这是最常用的一种遍历对象的方式:

js 复制代码
const result = [];
for ( const key in obj ) {
    result.push( key );
}
console.log( result );

结果如下:

css 复制代码
[ 'a', 'b', 'c', 'x', 'y' ]

可以看到,并没有返回预期的结果。这里就需要弄清楚 for...in 的遍历规则它只会遍历 "可枚举属性",而 Symbol 类型是不可枚举的,enumerable: false 的属性也是不可枚举的,因此均无法通过 for...in 遍历出来,并且除自身属性外,它还会遍历继承的属性 。所以,for...in 无法满足我们的需求。

方案二:Object.keys()

现在我们来试一下 Object.keys() 方式:

js 复制代码
console.log( Object.keys( obj ) );

结果如下:

js 复制代码
[ 'a', 'b', 'c' ]

由结果可见,Object.keys() 只会遍历自身的属性,不会遍历继承属性,这一点符合我们的需求,但是它依旧无法遍历出那些不可枚举的属性。

方案三:Object.getOwnPropertyNames()

我们再试试这个方法:

js 复制代码
console.log( Object.getOwnPropertyNames( obj ) );

结果如下:

js 复制代码
[ 'a', 'b', 'c', 'd' ]

这里我们发现,Object.getOwnPropertyNames() 同样也只会遍历自身的属性,不会遍历继承属性,并且它还能遍历出 enumerable: false 的不可枚举属性,但对于 Symbol 属性它却无能为力。这距离我们的需求就只差一个 Symbol 属性的问题了,我们可以借助另一个方法辅助它来实现我们的需求,这个方法是 Object.getOwnPropertySymbols(),它会返回对象自身的所有 Symbol 属性,两者结合起来就满足了我们的需求,代码如下:

js 复制代码
const props = Object.getOwnPropertyNames( obj );
const symbols = Object.getOwnPropertySymbols( obj );
console.log( props.concat( symbols ) );

结果如下:

js 复制代码
[ 'a', 'b', 'c', 'd', Symbol(1), Symbol(2) ]

这种方案借助了两个方法实现了最终需求,不过略显繁琐,下面的方案四则提供了终极方案。

方案四:Reflect.ownKeys()

这个方法用最简单的方式实现了我们的需求,代码如下:

js 复制代码
console.log( Reflect.ownKeys( obj ) );

结果如下:

js 复制代码
[ 'a', 'b', 'c', 'd', Symbol(1), Symbol(2) ]

此方法会返回一个数组,包含了指定对象的所有自身属性,包括可枚举和 enumerable: false 的不可枚举属性,以及 Symbol 属性。

相关推荐
lbh3 小时前
当我开始像写代码一样和AI对话,一切都变了
前端·openai·ai编程
We་ct4 小时前
LeetCode 918. 环形子数组的最大和:两种解法详解
前端·数据结构·算法·leetcode·typescript·动态规划·取反
qq_406176144 小时前
深入浅出 Pinia:Vue3 时代的状态管理新选择
javascript·vue.js·ecmascript
wefly20175 小时前
m3u8live.cn 在线M3U8播放器,免安装高效验流排错
前端·后端·python·音视频·前端开发工具
C澒5 小时前
微前端容器标准化 —— 公共能力篇:通用打印
前端·架构
德育处主任Pro5 小时前
前端元素转图片,dom-to-image-more入门教程
前端·javascript·vue.js
木斯佳5 小时前
前端八股文面经大全:小红书前端一二面OC(下)·(2026-03-17)·面经深度解析
前端·vue3·proxy·八股·响应式
陈天伟教授6 小时前
人工智能应用- 预测新冠病毒传染性:04. 中国:强力措施遏制疫情
前端·人工智能·安全·xss·csrf
叫我一声阿雷吧6 小时前
JS 入门通关手册(23):JS 异步编程:回调函数与异步本质
javascript·es6·前端面试·回调函数·回调地狱·js异步编程·异步本质
zayzy6 小时前
前端八股总结
开发语言·前端·javascript