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 | ✔ | ✔ | ✔ | ✘ |
- for of 获得的是属性值,不是属性键
- 能遍历到原型属性的只有 for in
- Reflect.ownKeys 综合来看是最强大的
- for of一般不能遍历对象,,如果实现了Symbol.iterator,可以遍历。 如Array,Map,Set,String,TypedArray,arguments 对象等等
综合来看Relect.ownKeys功能强大,能取到Symbol和普通属性,不可枚举的属性也能获取。 但属性复制的时候经常采用的是for in+ Object.hasOwnProperty 双层判断。
写在最后
不忘初衷,有所得,而不为所累,如果你觉得不错,你的一赞一评就是我前行的最大动力。
技术交流群请到 这里来。 或者添加我的微信 dirge-cloud,一起学习。