js获取对象属性的值(讲解js遍历对象属性名获取属性值)

1. 实例属性和原型属性

JavaScript中对象的属性分为两种:数据属性和访问器属性。

根据具体的上下文环境的不同,又可以将属性分为:原型属性和实例属性。

原型属性是定义在对象的原型prototype中的属性,

实例属性一方面来自构造的函数中,然后就是构造函数实例化后添加的新属性。

2. js的枚举

JavaScript中遍历一个对象的属性并不太简单,主要有两个原因:

JavaScript中的对象通常都处在某个原型链中,它会从一个或多个的上层原型上继承一些属性

JavaScript中的属性不光有值,它还有一些除了值以外的其他特性,其中一个影响属性遍历的特性就是Enumerable(一个属性描述符) ,如果该值为true,则这个属性是可枚举的,否则反之

2.1. 属性描述符

属性描述符主要有两种形式:数据描述符和存取描述符。

Object.getOwnPropertyDescriptor与Object.getOwnPropertyDescriptors两个方法获取对象的属性描述符。

var obj = { name: ’10’, _age: 25,get age(){return this._age; },set age(age){if(age<1){throw new Error(‘Age must be more than 0′); }else{this._age = age; } }};var des = Object.getOwnPropertyDescriptors(obj);console.log(des);/** * des: { * name: { * configurable: true, * enumerable: true, * value: “10”, * writable: true, * __proto__: Object * }, * _age: { * configurable: true, * enumerable: true, * value: 25, * writable: true, * __proto__: Object * }, * age: { * configurable: true, * enumerable: true, * get: f age(), * set: f age(age), * __proto__: Object * }, * __proto__: Object * }*/

value

该属性的值(仅针对数据属性描述符有效)

writable

当writable属性设置为false时,该属性被称为“不可写”。它不能被重新分配。

get

获取该属性的访问器函数(getter)。如果没有访问器, 该值为undefined。(仅针对包含访问器或设置器的属性描述有效)

set

获取该属性的设置器函数(setter)。如果没有设置器, 该值为undefined。(仅针对包含访问器或设置器的属性描述有效)

configurable

configurable特性表示对象的属性是否可以被删除,以及除writable特性外的其他特性是否可以被修改。

enumerable

enumerable定义了对象的属性是否可以在for…in循环和Object.keys()中被枚举。

1. name与_age拥有’configurable’、’enumerable’、’value’、’writable’四个属性描述符,统称数据描述符

2.age拥有’configurable’、’enumerable’、’get’、’set’四个属性描述符,统称存取描述符

分类数据描述符存取描述符configurableyesyesenumerableyesyesvalueyesnowritableyesnogetnoyessetnoyes

对象的属性描述符是可以通过两个方法来进行修改的,通过defineProperty和defineProperties来修改(configurable为true的条件下)

3. 常用的遍历方法3.1 for…in…遍历

遍历自身及原型链上所有可枚举的属性

使用 for…in 循环遍历对象属性时返回的属性会因为各个浏览器不同导致对象属性遍历的顺序有可能不是当初构建时的顺序。

Chrome Opera 的 JavaScript 解析引擎遵循的是新版 ECMA-262 第五版规范。因此,使用 for-in 语句遍历对象属性时遍历书序并非属性构建顺序。而 IE6 IE7 IE8 Firefox Safari 的 JavaScript 解析引擎遵循的是较老的 ECMA-262 第三版规范,属性遍历顺序由属性构建的顺序决定。for-in 语句无法保证遍历顺序,应尽量避免编写依赖对象属性顺序的代码。如果想顺序遍历一组数据,请使用数组并使用 for 语句遍历。var Animal = function({name=’none’, age=3, weight=80}={}){this.name = name;this.age = age;this.weight = weight;}Animal.prototype = {color: ‘red’}var dog = new Animal()// 将weight属性设置为 不可枚举Object.defineProperty(dog, ‘weight’, {enumerable: false})for(let i in dog){console.log(n);}//原型链上的color同样被遍历出来了,并且由于weight属性被设置成了enumerable:false,所以不可被遍历//name//age//color3.2. for…of遍历

一个数据结构只要部署了Symbol.iterator属性,就被视为具有iterator接口,就可以用for…of循环遍历它的成员。也就是说,for…of循环内部调用的是数据结构的Symbol.iterator方法。

for…of循环可以使用的范围包括数组、Set和Map结构、某些类似数组的对象(比如arguments对象、DOM NodeList 对象)、Generator 对象,以及字符串。

如果不太清楚iterator,请去看看阮一峰大神的这篇文章,里面关于for…of以及iterator都讲的非常详细!

其实for…of和for…in都是迭代一些东西,它们之间的主要区别在于它们的迭代方式。

for…in语句以原始插入顺序迭代对象的可枚举属性。

for…of语句遍历可迭代对象定义要迭代的数据。

请仔细看以下实例,理解其中的区别

Object.prototype.objCustom = function() {};Array.prototype.arrCustom = function() {};let iterable = [3, 5, 7];iterable.foo = ‘hello’;for (let i in iterable) {console.log(i); // 0, 1, 2, “foo”, “arrCustom”, “objCustom”}for (let i in iterable) {if (iterable.hasOwnProperty(i)) {console.log(i); // 0, 1, 2, “foo” }}for (let i of iterable) {console.log(i); // 3, 5, 7}Object.prototype.objCustom = function() {};Array.prototype.arrCustom = function() {};let iterable = [3, 5, 7];iterable.foo = ‘hello’;

在这段代码里面,由于继承和原型链,对象iterable继承属性objCustom和arrCustom。

for (let i in iterable) { console.log(i); // 0, 1, 2, “foo”, “arrCustom”, “objCustom”}

在这段代码里面,此循环仅以原始插入顺序记录iterable对象的可枚举属性。它不记录数组元素3, 5, 7或hello,因为这些不是枚举属性。但是它记录了数组索引以及arrCustom和objCustom(为何记录arrCustom和objCustom在本文for…in里面有讲过)。

for (let i in iterable) {if (iterable.hasOwnProperty(i)) {console.log(i); // 0, 1, 2, “foo” }}

hasOwnProperty()用来检查找到的枚举属性是不是对象自己的(即是不是继承的)

for (let i of iterable) {console.log(i); // 3, 5, 7}

该循环迭代并记录iterable作为可迭代对象定义的迭代值,这些是数组元素 3, 5, 7,而不是任何对象的属性。

3.3. Object.keys遍历

Object.keys()方法会返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和使用for…in循环遍历该对象时返回的顺序一致 (两者的主要区别是 一个for-in循环还会枚举其原型链上的属性)。

Object.getOwnPropertyNames()遍历

Object.getOwnPropertyNames()方法返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性但不包括Symbol值作为名称的属性)组成的数组,此方法不会获取原型链上的属性。

var Animal = function({name=”, age=1, weight=70}={}){this.name = name;this.age = age;this.weight = weight;}Animal.prototype = {type: ‘Animal’}var dog = new Animal()// 将height属性设置为 不可枚举Object.defineProperty(dog, ‘weight’, {enumerable: false})var keys = Object.getOwnPropertyNames(dog);console.log(keys)// [‘name’, ‘age’, ‘weight’]4. 结语

希望这篇文章能让大家更加理解js中的遍历。

最近工作较忙,来不及写新文章,翻了翻之前的文章库存,顺便进行复习与巩固。

争取做到一天一更,望大家多多支持!

发表评论

登录后才能评论