这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助

for in 和 for of 相对于大家肯定都不陌生,都是用来遍历属性的没错。那么先看下面的一个例子:

例1

const obj = {
a: 1,
b: 2,
c: 3
}
for (let i in obj) {
console.log(i)
// a
// b
// c
}
for (let i of obj) {
console.log(i)
// Uncaught TypeError: obj is not iterable 报错了
}

以上代码通过 for in 和 for of 对一个obj对象进行遍历,for in 正常的获取了对象的 key值,分别打印 a、b、c,而 for of却报错了。

例2:

以上是遍历对象,下面再看一个遍历数组的例子。

    const arr = ['a', 'b', 'c']
// for in 循环
for (let i in arr) {
console.log(i)
// 0
// 1
// 2
} // for of
for (let i of arr) {
console.log(i)
// a
// b
// c
}

以上代码是对一个数组进行遍历, for in 返回的值为 0、1、2,这不是数组的下标吗? 而 for of 返回的是 a、b、c,这一次没有报错,为什么呢?

例3

    const arr = ['a', 'b']
// 手动给 arr数组添加一个属性
arr.name = 'qiqingfu' // for in 循环可以遍历出 name 这个键名
for (let i in arr) {
console.log(i)
// a
// b
// name
}

for in 的特点

结合上面的两个例子,分析得出:

  • for ... in 循环返回的值都是数据结构的 键值名。

  • 遍历对象返回的对象的key值,遍历数组返回的数组的下标(key)。

  • for ... in 循环不仅可以遍历数字键名,还会遍历原型上的值和手动添加的其他键。如——例3

  • 特别情况下, for ... in 循环会以看起来任意的顺序遍历键名

(为什么说看起来,其实也是有规律的,这个就要扯到 常规属性和 排序属性,想深入学习的可以看读李老课程引发的思考之JS设计思想篇

这里可以简单说一下

1.什么是对象中的 常规属性和 排序属性

function Foo() {
this[100] = 'test-100'
this[1] = 'test-1'
this["B"] = 'bar-B'
this[50] = 'test-50'
this[9] = 'test-9'
this[8] = 'test-8'
this[3] = 'test-3'
this[5] = 'test-5'
this["A"] = 'bar-A'
this["C"] = 'bar-C'
}
var bar = new Foo()
for(key in bar){
console.log(`index:${key} value:${bar[key]}`)
}

在上⾯这段代码中,我们利⽤构造函数Foo创建了⼀个bar对象,在构造函数中,我们给bar对象设置了很多 属性,包括了数字属性和字符串属性,然后我们枚举出来了bar对象中所有的属性,并将其⼀⼀打印出来, 下⾯就是执⾏这段代码所打印出来的结果

index:1 value:test-1
index:3 value:test-3
index:5 value:test-5
index:8 value:test-8
index:9 value:test-9
index:50 value:test-50
index:100 value:test-100
index:B value:bar-B
index:A value:bar-A
index:C value:bar-C

观察这段打印出来的数据,我们发现打印出来的属性顺序并不是我们设置的顺序,我们设置属性的时候是乱 序设置的,⽐如开始先设置100,然后有设置了1,但是输出的内容却⾮常规律,总的来说体现在以下两 点:

设置的数字属性被最先打印出来了,并且按照数字⼤⼩的顺序打印的;

设置的字符串属性依然是按照之前的设置顺序打印的,⽐如我们是按照B、A、C的顺序设置的,打印出来,依然是这个顺序。

之所以出现这样的结果,是因为在ECMAScript规范中定义了 「数字属性应该按照索引值⼤⼩升序排列,字符 串属性根据创建时的顺序升序排列。」在这⾥我们把对象中的数字属性称为 「排序属性」,在V8中被称为 elements,字符串属性就被称为 「常规属性」, 在V8中被称为 properties。在V8内部,为了有效地提升存储和访问这两种属性的性能,分别使⽤了两个 线性数据结构来分别保存排序 属性和常规属性,具体结构如下图所⽰:

在elements对象中,会按照顺序存放排序属性,properties属性则指向了properties对 象,在properties对象中,会按照创建时的顺序保存了常规属性。

总结一句: for in 循环特别适合遍历对象。

for of 特点

for of 循环用来获取一对键值对中的值,而 for in 获取的是 键名

一个数据结构只要部署了 Symbol.iterator 属性, 就被视为具有 iterator接口, 就可以使用 for of循环。

例1这个对象,没有 Symbol.iterator这个属性,所以使用 for of会报 obj is not iterable

for of 不同与 forEach, 它可以与 break、continue和return 配合使用,也就是说 for of 循环可以随时退出循环。

提供了遍历所有数据结构的统一接口

哪些数据结构部署了 Symbol.iteratoer属性了呢?

只要有 iterator 接口的数据结构,都可以使用 for of循环。

  • 数组 Array

  • Map

  • Set

  • String

  • arguments对象

  • Nodelist对象, 就是获取的dom列表集合

-以上这些都可以直接使用 for of 循环。 凡是部署了 iterator 接口的数据结构也都可以使用数组的 扩展运算符(...)、和解构赋值等操作。

我也想让对象可以使用 for of循环怎么办?使用 Object.keys() 获取对象的 key值集合后,再使用 for of

以例1为例

 const obj = {
a: 1,
b: 2,
c: 3
} for (let i of Object.keys(obj)) {
console.log(i)
// 1
// 2
// 3
}

也可以给一个对象部署 Symbol.iterator属性。

本文转载于:

https://juejin.cn/post/6854573212039151629

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

记录--for in 和 for of的区别详解以及为for in的输出顺序的更多相关文章

  1. Bind和Eval的区别详解

    原文:Bind和Eval的区别详解 1.简单描述Eval和Bind的区别 绑定表达式 <%# Eval("字段名") %> <%# Bind("字段名& ...

  2. MySQL单列索引和组合索引(联合索引)的区别详解

    发现index merge局限性,优化器会自动判断是否使用 index merge 优化技术,查询还是需要组合索引[推荐阅读:对mysql使用索引的误解] MySQL单列索引和组合索引(联合索引)的区 ...

  3. 基于Java的打包jar、war、ear包的作用与区别详解

      本篇文章,小编为大家介绍,基于Java的打包jar.war.ear包的作用与区别详解.需要的朋友参考下   以最终客户的角度来看,JAR文件就是一种封装,他们不需要知道jar文件中有多少个.cla ...

  4. Android中Intent传值与Bundle传值的区别详解

    Android中Intent传值与Bundle传值的区别详解 举个例子我现在要从A界面跳转到B界面或者C界面   这样的话 我就需要写2个Intent如果你还要涉及的传值的话 你的Intent就要写两 ...

  5. php 去除html标记--strip_tags与htmlspecialchars的区别详解

    php 去除html标记--strip_tags与htmlspecialchars的区别详解 作者: 字体:[增加 减小] 类型:转载 时间:2013-06-26   本篇文章是对php中去除html ...

  6. HTTP POST GET 本质区别详解

    HTTP POST GET 本质区别详解 一 原理区别 一般在浏览器中输入网址访问资源都是通过GET方式:在FORM提交中,可以通过Method指定提交方式为GET或者POST,默认为GET提交 Ht ...

  7. javascript中=、==、===区别详解

    javascript中=.==.===区别详解今天在项目开发过中发现在一个小问题.在判断n==""结果当n=0时 n==""结果也返回了true.虽然是个小问题 ...

  8. [转]ESCAPE()、ENCODEURI()、ENCODEURICOMPONENT()区别详解

    escape().encodeURI().encodeURIComponent()区别详解 JavaScript中有三个可以对字符串编码的函数,分别是: escape,encodeURI,encode ...

  9. phpcms加载系统类与加载应用类之区别详解

    <?php 1. 加载系统类方法load_sys_class($classname, $path = ''", $initialize = 1)系统类文件所在的文件路径:/phpcms ...

  10. 转-HTTP POST GET SOAP本质区别详解

    原文链接:HTTP POST GET SOAP本质区别详解 一 原理区别 一般在浏览器中输入网址访问资源都是通过GET方式:在FORM提交中,可以通过Method指定提交方式为GET或者POST,默认 ...

随机推荐

  1. STC12C5A56S2和DS12C887做的电子闹铃

    配件信息 控制器: STC12C5A56S2 定时芯片: DS12C887 显示: 4位0.56寸数码管 其它: 无源蜂鸣器, 三极管S9012, 电阻10K*2, 100*1, 电容30p*2, 1 ...

  2. 基于keras的残差网络

    1 前言 理论上,网络层数越深,拟合效果越好.但是,层数加深也会导致梯度消失或梯度爆炸现象产生.当网络层数已经过深时,深层网络表现为"恒等映射".实践表明,神经网络对残差的学习比对 ...

  3. OpenStack调度器

    计算使用 nova-scheduler 服务来确定如何调度计算请求 默认配置中,调度程序会考虑以下所有条件的主机: 位于请求的可用区 (map_az_to_placement_aggregate) 放 ...

  4. wordpress设置固定链接404及伪静态配置

    说明 最近在将wordpress设置中文章url修改为月份和名称型 之后访问文章出现404.原因是配有配置好apache的伪静态. 配置步骤 1.修改httpd.conf 我这里是centos7,默认 ...

  5. Java中的包装类(wrapper class)

    1.介绍 顾名思义,包装类是封装Java原始类型的对象.每个Java原始类型都有一个对应的包装类: 基本类型 包装类 boolean Boolean byte Byte short Short cha ...

  6. pyhotn3.8 apt机器基础镜像构建

    FROM python:3.8.10-slim RUN sed -i 's/deb.debian.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apt/source ...

  7. String--cannot convert from 'const char *' to 'LPTSTR'错误

    这种错误,很多情况下是类型不匹配 LPTSTR表示为指向常量TCHAR字符串的长指针 TCHAR可以是wchar_t或char,基于项目是多字节还是宽字节版本. 看下面的代码,代码来源:Example ...

  8. itext 生成 PDF

    itext 生成 PDF(一) 转自:https://blog.csdn.net/lcczpp/article/details/125424395   itext生成PDF excel 示例  转自: ...

  9. 【系统设计】集团内部HR系统完结,项目从0到1总结

    最近一年学习了PMP,结合下PMP的知识,分享一下最近HR项目的全生命周期流程管理(需求分析.产品设计.系统开发.测试.上线.运营). 先一句话概括:战略分析-收集需求-流程梳理-关键需求-IT规划- ...

  10. 合并区间(区间排序,vector的动态扩容的应用)

    以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] .请你合并所有重叠的区间,并返回一个不重叠的区间数组,该数组需恰好覆盖输入 ...