摘要:简单说就是一个有一个函数,这个函数执行的返回值一定是一个对象,对象有两个属性标记迭代是否结束,标记这次迭代的结果值。
引言
遍历对象是平常工作中很常见的一个操作,几乎是日常操作,但是遍历对象真的是一件很容易的事情么,显然不是的。
常用的方式 for...infor (variable in object) {...}
这个是一个很常见的用法,相信每个人顺手都可以写出来。但是这里需要主要的是一段这个遍历的定义
for...in语句以任意顺序遍历一个对象自有的、继承的、可枚举的、非Symbol的属性。对于每个不同的属性,语句都会被执行。
一个一个词抠吧。
对象自有的如果一个key是对象自有的那么一定可以用obj.hasOwnProperty(prop)的返回值来判断
继承的这个也很好理解,比如下面的例子
var parent = {a: 1}; function child() { this.b = "b"; } child.prototype = parent; var obj = new child();
此时由于obj的原型链继承了parent,所以其实obj是有a属性的。换句话说for in会遍历对象原型链上的属性
可枚举的什么是可枚举的详细的可以看一下这个链接
首先对象的属性分为两种,数据属性如a["b"]=1,这个就是数据属性,另一种就是访问器属性,也就是我们用的getter。
这两种属性都有一个特性的[[Enumerable]],这个布尔值代表了这个属性是否可以被枚举。如果一个对象的属性被设定为不可枚举,那么for in并不可以遍历到。可枚举性可以用propertyIsEnumerable来判断。
Symbol是什么这里不展开说了不熟悉的建议看一下es6 symbol
symbol可以被用作给某个对象做私有属性,而如果属性值是symbol类型的那么for in也是无法遍历的。
综上可以明确的知道到底对象的哪些属性可以用for in去遍历出来了,坑点在基础和可枚举。数组遍历我们会自然的去用for in,但是大家是否考虑过,数组也是一个对象,为什么我们再用for in的时候不会把数组的长度,length作为一个属性遍历到呢,原因也就是length属性其实是一个不可枚举属性
Object.keys()Object.keys() 方法会返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和使用 for...in 循环遍历该对象时返回的顺序一致。
注意点这里和for in有一个很大的区别,就是这个返回的是对象自身可枚举属性组成的数组,不包含继承
var parent = {a: 1}; function child() { this.b = "b"; } child.prototype = parent; var obj = new child(); Object.keys(obj); //["b"]Object.getOwnPropertyNames(obj)与Object.getOwnPropertySymbols(obj)
getOwnPropertyNames方法返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性但不包括Symbol值作为名称的属性)组成的数组。
getOwnPropertySymbols方法返回一个给定对象自身的所有 Symbol 属性的数组。
关键词,所有的,自身的。这两个方法不受是否可枚举属性的限制,而且是只返回自身的,所以Object.getOwnPropertyNames的返回值一定是包含了Object.keys的返回值
Reflect.ownKeys 方法返回一个由目标对象自身的属性键组成的数组。它的返回值等同于Object.getOwnPropertyNames(target).concat(Object.getOwnPropertySymbols(target))。
for...of接下来说说另一种遍历的方案。for of 与for in 不同的就是for of是在可迭代对象(包括 Array,Map,Set,String,TypedArray,arguments 对象等等)上创建一个迭代循环,调用自定义迭代钩子,并为每个不同属性的值执行语句。下面还是进入抠关键词的阶段
可迭代对象什么是可迭代对象?遵循有可迭代协议的对象成为可迭代对象,用人话说就是一个对象如果有[Symbol.iterator],那么他就是可迭代对象。Symbol.iterator是es6提供了 1个内置的 Symbol 值。
iterator简单说就是一个有一个next函数,这个函数执行的返回值一定是一个对象,对象有两个属性done标记迭代是否结束,value标记这次迭代的结果值。
综上所述也就是说给你的要遍历的对象增加一个Symbol.iterator就可以了
拓展运算符除了上面说的还想再补充一种遍历的场景,对象的拓展运算符,那么对象的拓展运算符究竟是有哪些属性可以被赋值。
自身的,可枚举的。可以看两个例子
var obj = {} Object.defineProperty(obj, "key", { enumerable: false, configurable: true, writable: true, value: "a" }); b = {...obj}; console.log(b); //{}
可以看到不可枚举属性在解构赋值中是不可被赋值的。
var parent = {a: 1}; function child() { this.b = "b"; } child.prototype = parent; var obj = new child(); var b = {...obj}; console.log(b);//{b: "b"}
可以看到继承的属性在解构赋值中是不可被赋值的。
总结对象的遍历方法很多,但是要根据具体对象属性的特征和应用场景,还有兼容性来选择最适合的遍历方案。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/109758.html
摘要:遍历对象的属性并没有像中遍历一个那么简单,主要原因有以下两点在中对象的属性分为可枚举与不可枚举之分他们是由属性的的值决定的。 javascript遍历对象的属性并没有像java中遍历一个Map那么简单,主要原因有以下两点: 在javascript中对象的属性分为可枚举与不可枚举之分,他们是由属性的 enumerable 的值决定的。可枚举性 决定了这个属性是否可以被 for-in ...
摘要:日常开发中我们难免需要对数组和对象进行遍历,今天抽空来总结下遍历数组和对象常用的方法。使用遍历对象注只能遍历出自身可枚举的属性,而不能遍历出原型链上面的属性。 日常开发中我们难免需要对数组和对象进行遍历,今天抽空来总结下遍历数组和对象常用的方法。 Javascript遍历数组总结 我们定义一个数组 var arr = [2,4,6]; 1.使用for循环遍历 var lengt...
摘要:所以说遍历属性时,要考虑这两个因素。开始遍历先定义两个类吧和,后者继承前者。然后再声明并初始化一个的实例。 原文链接 JavaScript 中遍历对象的属性 参考 JavaScript中的属性:如何遍历属性《JavaScript 高级程序设计》 概述 遍历 JavaScript 对象中的属性没有其他语言那么简单,因为两个因素会影响属性的遍历:对象属性的属性描述符 (property ...
摘要:接触这么多年,第一次总结一下它的遍历语法。而且你必须借助特定的结构才能遍历数据结构。它的作用是遍历对象的键名。建议仅在遍历数组的时候使用。另一个优点是,它可以遍历任何部署了接口的数据结构,甚至是非的数据类型,即自己定义的数据结构。 接触JavaScript这么多年,第一次总结一下它的遍历语法。以前我大部分时间都在老版本的JavaScript下写代码,所以大部分时间都是用for...in...
摘要:文章内容分两部分前半部分为迭代器模式概念后半部分为中迭代器上半部分开始迭代器模式提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。下半部分开始的迭代器迭代器等同于遍历器。执行该函数,会返回一个遍历器对象。 showImg(https://segmentfault.com/img/bVbuyaZ?w=800&h=600); 文章内容分两部分: 前半部分为 迭...
摘要:总结中的循环遍历定义一个数组和对象经常用来遍历数组元素遍历值为数组元素索引用来遍历数组元素第一个参数为数组元素,第二个参数为数组元素索引,第三个参数为数组本身可选没有返回值用来遍历数组元素第一个参数为数组元素,第二个参数为数组元素索引,第三 总结JavaScript中的循环遍历 定义一个数组和对象 const arr = [a, b, c, d, e, f]; const obj = ...
阅读 1786·2021-08-13 15:06
阅读 3074·2021-08-05 10:02
阅读 3342·2019-08-30 15:55
阅读 2342·2019-08-30 13:46
阅读 2456·2019-08-30 13:01
阅读 1308·2019-08-29 17:17
阅读 2809·2019-08-29 15:27
阅读 1402·2019-08-29 11:12