【每日一题】Reflect.ownKeys 与 Object.keys 的区别
人生苦短,总需要一点仪式感。比如学前端~
用法上
两个函数都是接受一个对象参数,并都是以数组形式返回对象属性的集合。
而且参数都必须是对象,如果是其他乱麻七糟的类型,会报错
Reflect.ownKeys(targetObj)
Object.keys(targetObj)
不同之处
关于对象属性是否可枚举
Reflect.ownKeys()
可以得到对象自己的所有属性,包括不可枚举属性;Object.keys()
只能得到对象的普通可枚举属性,拿不到不可枚举属性。
关于Symbol属性
Reflect.ownKeys()
可以拿到对象的Symbol 的属性;Object.keys()
不行。
关于数组的length属性
因为Reflect.ownKeys()
可以得到对象的不可枚举属性这个特点,所以当目标对象是数组对象时,我们可以看到获取的结果会比Object.keys()
多一个length属性
事实证明,数组的length也确实是“不可枚举的”:
关于对象的原型
俩人这点上谁也不比谁强,都拿不到原型链上的属性。
不过还好,这点需求上,可以用for...in
来替代。
总结
分类表格
整理一个看上去更清晰的表格如下(感谢群友给的灵感)
方法分类 | 普通属性 | 不可枚举属性 | Symbol属性 | 原型属性 | 数组length |
---|---|---|---|---|---|
Reflect.ownKeys() | ✅ | ✅ | ✅ | ❌ | ✅ |
Object.keys() | ✅ | ❌ | ❌ | ❌ | ❌ |
for...in | ✅ | ❌ | ❌ | ✅ | ❌ |
数组length其实就是不可枚举属性那一列的延伸。
测试代码汇总:
Object.prototype.pr = "我是原型属性"; // 原型上增加“pr”属性
let s = Symbol();
let obj = {
[s]: "this is Symbol", // 增加一个Symbol属性“[s]”
a: "a", // 一个普通属性“a”
};
// 再定义一个不可枚举的属性“name”
Object.defineProperty(obj, "name", {
value: "sunny",
configurable: true,
enumerable: false, // *
writable: true,
});
// 观察打印结果
console.log("Object.keys", Object.keys(obj)); // 只得到一个普通属性:["a"]
console.log("Reflect.ownKeys(obj)", Reflect.ownKeys(obj)); // 得到普通属性,以及symbol和不可枚举属性:["a", "name", Symbol()]
// 遗憾的是,二者都拿不到 原型上的属性“pr”。我们用for in来获取
for(let o in obj){
console.log(o) // 分别打印:a、pr
}
看来for in也不能获取symbol属性和不可枚举属性🤦♀️……
让我们一起携手同走前端路!
评论