本篇文章给大家分享的内容是关于详解js中的遍历 问题,有着一定的参考价值,有需要的朋友可以参考一下
实例属性和原型属性
JavaScript中对象的属性分为两种: 数据属性 和 访问器属性 。
根据具体的上下文环境的不同,又可以将属性分为: 原型属性 和 实例属性 。
原型属性 是定义在对象的原型prototype 中的属性,
实例属性 一方面来自构造的函数中,然后就是构造函数实例化后添加的新属性。
js的枚举
JavaScript中遍历一个对象的属性并不太简单,主要有两个原因:
JavaScript中的对象通常都处在某个原型链中,它会从一个或多个的上层原型上继承一些属性
JavaScript中的属性不光有值,它还有一些除了值以外的其他特性,其中一个影响属性遍历的特性就是Enumerable(一个属性描述符) ,如果该值为 true ,则这个属性是可枚举的,否则反之
属性描述符
属性描述符 主要有两种形式:数据描述符和存取描述符。
使用Object.getOwnPropertyDescriptor 与 Object.getOwnPropertyDescriptors两个方法获取对象的属性描述符。
- var obj = { name: '10', _age: 25, get age(){ return this._age; }, set age(age){ if(age
value
该属性的值(仅针对数据属性描述符有效)
writable
当writable属性设置为false时,该属性被称为“不可写”。它不能被重新分配。
get
获取该属性的访问器函数(getter)。如果没有访问器, 该值为undefined。(仅针对包含访问器或设置器的属性描述有效)
set
获取该属性的设置器函数(setter)。 如果没有设置器, 该值为undefined。(仅针对包含访问器或设置器的属性描述有效)
configurable
configurable特性表示对象的属性是否可以被删除,以及除writable特性外的其他特性是否可以被修改。
enumerable
enumerable定义了对象的属性是否可以在 for...in 循环和 Object.keys() 中被枚举。
登录后复制
name、_age拥有 ‘configurable’、’enumerable’、’value’、’writable’四个属性描述符,统称数据描述符
age拥有’configurable’、’enumerable’、’get’、’set’四个属性描述符,统称存取描述符
分类 ‘configurable’ ‘enumerable’ ‘value’ ‘writable’ ‘get’ ‘set’数据描述符yesyesyesyesnono存取描述符yesyesnonoyesyes
对象的属性描述符,可以通过Object.defineProperty和Object.defineProperties来修改(configurable为true的条件下)
常用的遍历方法
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 //color
登录后复制
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,而不是任何对象的属性。
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']
登录后复制
结语
这篇文章希望能让大家更加理解js中的遍历,写的不好多多见谅并指出!
相关推荐:
实例详解AngularJS遍历获取数组元素
JS遍历对象属性的方法示例
JS遍历页面所有对象属性及实现方法
以上就是详解js中的遍历 问题的详细内容,更多请关注【创想鸟】其它相关文章!