属性遍历,会了又没完全会

·  阅读 914
属性遍历,会了又没完全会

1. 属性的分类

  • 普通属性
  • 原型属性
  • 不可枚举属性
  • Symbol 属性
  • 静态属性 ??

我们先来看看下面这个对象。

const symbolIsAnimal = Symbol.for("pro_symbol_attr_isAnimal");
const symbolSay = Symbol.for("pro_symbol_method_say");
const symbolSalary = Symbol.for("ins_symbol_attr_salary");

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

    this.ins_in_method_walk = function () {
        console.log("ins_method_walk");
    }
}


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


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

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

    //Symbol 属性
person[symbolSalary] = 6000;
person["ins_no_enumerable_attr_sex"] = "男";


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

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

我们来归类下,这些都属于哪些属性分类。

了解属性分类以后,让我们再想想 我们又如何获取person 对象的所有属性呢??

遍历对象的属性

1. for in

for(let i in person){
    console.log("for in===",i);
}

// for in=== ins_in_attr_age
// for in=== ins_in_attr_name
// for in=== ins_in_method_walk
// for in=== pro_method_say
// for in=== pro_attr_isAnimal
复制代码

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

2. Object.keys

const keys=Object.keys(person);

console.log("Object.keys==",keys)

// Object.keys== [ 'ins_in_attr_age', 'ins_in_attr_name', 'ins_in_method_walk' ]Object.keys== [ 'age', 'name', 'walk' ]
复制代码

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

3. Object.getOwnPropertyNames

const names=Object.getOwnPropertyNames(person);
console.log("Object.getOwnPropertyNames==",names);

//
// Object.getOwnPropertyNames== [
//  'ins_in_attr_age',
//  'ins_in_attr_name',
//  'ins_in_method_walk',
//  'ins_no_enumerable_attr_sex'
// ]
复制代码

返回对象所有普通属性键 ,包括不可枚举属性但不包括Symbol值作为名称的属性键和原型属性。

4. Object.getOwnPropertySymbols

    //Symbol 属性
person[symbolSalary] = 6000;

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

const keys=Object.getOwnPropertySymbols(person);
console.log("Object.getOwnPropertySymbols==",keys);
console.log("描述符是否生效==",person[symbolSalary])


// Object.getOwnPropertySymbols== [ Symbol(ins_symbol_attr_salary) ]
// 描述符是否生效== 999
复制代码

返回一个给定对象自身的所有 Symbol 属性键的数组。包括不可枚举的Symbol属性。只限Symbol。

5. Reflect.ownKeys

const names=Reflect.ownKeys(person);
console.log("Object.getOwnPropertySymbols==",names);

// Reflect.ownKeys== [
//  'ins_in_attr_age',
//  'ins_in_attr_name',
//  'ins_in_method_walk',
//  'ins_no_enumerable_attr_sex',
//   Symbol(ins_symbol_attr_salary)
// ]
复制代码

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

6. for of

for...of 循环仅适用于可迭代的对象。 而普通对象不可迭代。在 ES6 中引入的 for...of 循环,以替代 for...in 和 forEach() ,并支持新的迭代协议。for...of 允许你遍历 Arrays(数组), Strings(字符串), Maps(映射), Sets(集合)等可迭代的数据结构等。

const obj = { fname: 'foo', lname: 'bar' };
 
for (const value of obj) { // TypeError: obj[Symbol.iterator] is not a function
    console.log(value);
}
复制代码
const array = ['foo', 'bar', 'baz'];
 

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

array[0]="apple";

for(let i of array){
    console.log("for of===",i);
}
console.log("=====分割=========");
for(let i in array){
    console.log("for in===",i);
}



// for of=== foo
// for of=== bar
// for of=== baz
// =====分割=========
// for in=== 1
// for in=== 2
 
复制代码

我们通过对比for in 可以很清楚的看到 0 索引的不可枚举属性已经生效。

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

总结

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

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

写在最后

不忘初衷,有所得,而不为所累,如果你觉得不错,你的一赞一评就是我前行的最大动力。

技术交流群请到 这里来。 或者添加我的微信 dirge-cloud,一起学习。

分类:
前端
收藏成功!
已添加到「」, 点击更改