几种方式获取对象的属性

815 阅读2分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

前言

获取对象的属性,是非常常规的操作。经常用于复制和拷贝对象,亦或是数据合并,或者判断属性是否存在,然后进行下一步的操作。

for in

可遍历原型上的属性键,不可枚举的属性和Symbol属性除外。

for of

可遍历原型上的属性值,包含不可枚举属性值,不能遍历原型上的值。

Object.keys

返回的是所有可枚举属性键,也就是属性下的enumerable: true。但不包括Symbol值作为名称的属性键。

Object.getOwnPropertyNames

回的是对象所有自己的属性键 ,包括不可枚举属性不包括Symbol值作为名称的属性键。

Object.getOwnPropertySymbols

方法返回一个给定对象自身的所有 Symbol 属性键的数组。

Reflect.ownKeys

返回一个由目标对象自身的属性键组成的数组。等同于Object.getOwnPropertyNames(target).concat(Object.getOwnPropertySymbols(target))。

表格对比

for of一般不能直接遍历对象,所以就单独说。

方法名普通属性不可枚举属性Symbol属性原型属性
for in
Object.keys
Object.getOwnPropertyNames
Object.getOwnPropertySymbols
Reflect.ownKeys
  1. for of 获得的是属性值,不是属性键
  2. 能遍历到原型属性的只有 for in
  3. Reflect.ownKeys 综合来看是最强大的
  4. for of一般不能遍历对象,,如果实现了Symbol.iterator,可以遍历。 如Array,Map,Set,String,TypedArray,arguments 对象等等

一起看一个例子:

const symbolSalary = Symbol.for("salary");
const symbolIsAnimal = Symbol.for("isAnimal");
const symbolSay = Symbol.for("say");

function Person(age, name){
    this.age = age;
    this.name = name;

    this.walk = function () {
        console.log("person:walk");
    }
}

// 原型方法
Person.prototype.say = function(words){
    console.log("say:", words);
}
Person.prototype[symbolSay] = function(words){
    console.log("symbolSay", words);
}

// 原型属性
Person.prototype[symbolIsAnimal] = true;
Person.prototype.isAnimal = true;

const person = new Person(100, "程序员");

person[symbolSalary] = 6000;
person["sex"] = "男";


// sex 不可枚举
Object.defineProperty(person, "sex", {
    enumerable: false
});

Object.defineProperty(person, symbolSalary, {
    enumerable: false, // 无效的设置 
    value: 999
});

const keys = Object.keys(person);

const names = Object.getOwnPropertyNames(person);

const symbols = Object.getOwnPropertySymbols(person);

const ownKeys = Reflect.ownKeys(person);

console.log("keys", keys);  // [ 'age', 'name', 'walk' ]
console.log("getOwnPropertyNames", names); // [ 'age', 'name', 'walk', 'sex' ]
console.log("getOwnPropertySymbols", symbolSalary); // [ Symbol(salary) ]
console.log("ownKeys", ownKeys); // [ 'age', 'name', 'walk', 'sex', Symbol(salary) ]


console.log("--------")
console.log(person.isAnimal);  // true
console.log(person[symbolIsAnimal]); // true
console.log(person[symbolSalary]);  // 999
person[symbolSay]("hello world"); // symbolSay hello world
person.say("hello world"); // say: hello world
person.walk(); // person:walk

综合来看Relect.ownKeys功能强大,能取到Symbol和普通属性,不可枚举的属性也能获取。 但属性复制的时候经常采用的是 for in + Object.hasOwnProperty 双层判断。

现在你觉得那种方式更合适呢?

小结

今天你收获了吗?