热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

[JavaScript]多数前端工程师都没注意到的一个关于console.log()的坑

[JavaScript]多数前端工程师都没注意到的一个关于console.log()的坑请阅读以下代码并猜测结果:functiontest(){le

[Javascript] 多数前端工程师都没注意到的一个关于console.log()的坑
请阅读以下代码并猜测结果:

      function test() {
        let obj = {}, arr=[]
          for(var i = 0; i <4; i++) { obj.first = i obj.secOnd= i+1 obj.three = i+2 arr.push(obj) }
        console.log(arr)
      }
      test()

输出结果为:
这里写图片描述
为什么输出结果不是以下这个?
这里写图片描述

我要说的坑不是这个,因为相信这个引用类型的赋值问题很多伙伴都能轻松解决。以下提供两种解决方案:
(方法一),将let obj={}移到for循环中,每次循环创建一个新对象:

      function test() {
        let arr=[]
          for(var i = 0; i <4; i++) { let obj = {}
            obj.first = i
            obj.secOnd= i+1
            obj.three = i+2
            arr.push(obj)
        }
        console.log(arr)
      }
      test()

能得到预期结果:
这里写图片描述

(方法二):使用ES6新特性Object.assign,轻松实现深复制,这样的好处是不用每次都创建一个新对象:

      function test() {
        let obj= {}, arr=[]
          for(var i = 0; i <4; i++) { obj.first = i obj.secOnd= i+1 obj.three = i+2 arr.push(Object.assign({}, obj))
        }
        console.log(arr)
      }
      test()

同样能得到预期结果:
这里写图片描述

问题都解决了,那么我说的坑是什么呢?
接下来我们将解决了以上问题的代码作出以下修改,将console.log移到循环中,如下:

      function test() {
        let obj= {}, arr=[]
          for(var i = 0; i <4; i++) { obj.first = i obj.secOnd= i+1 obj.three = i+2 arr.push(Object.assign({}, obj))
            console.log(arr)
        }
      }
      test()

请先预测一下结果是什么再看以下答案。
运行结果为:

这里写图片描述
每次循环输出的都是最后的值,是不是有点惊讶?我们再来看一点更惊讶的,在输出数组前数组一下数组的长度console.log(arr.length),如下:

      function test() {
        let obj= {}, arr=[]
          for(var i = 0; i <4; i++) { obj.first = i obj.secOnd= i+1 obj.three = i+2 arr.push(Object.assign({}, obj))
            console.log(arr.length)
            console.log(arr)
        }
      }
      test()

同样,先预测运行结果再看以下答案。
运行结果为:
这里写图片描述
第一次循环输出数组的长度是1,看起来也是只有一个对象,这很符合预期;但是为什么展开后,里边会有四个对象?第二次循环数组长度是2,看起来有两个对象,这符合预期,但是点开后为什么里边也是有四个对象?这就是我说的坑!!!

原因:
使用console.log()输出引用类型值时,console.log的实际执行会推迟,相当于“惰性”求值,遇上数组、对象这样的引用类型就出上面的问题了,也就是我们点击箭头打开的时候,才会输出真正的值,而这时候循环早就已经执行完了,所以输出的会是循环执行完后的结果!

测试
我们可以将arr转成非引用类型的数据格式,来证明我们的想法,如下:

      function test() {
        let obj= {}, arr=[]
          for(var i = 0; i <4; i++) { obj.first = i obj.secOnd= i+1 obj.three = i+2 arr.push(Object.assign({}, obj))
            console.log(arr.length)
            console.log(JSON.parse(JSON.stringify(arr)))
        }
      }
      test()

这里写图片描述
显然,结果已经符合预期,猜测正确!!

完结~ 午休一会~~~


推荐阅读
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 本文详细解析了JavaScript中相称性推断的知识点,包括严厉相称和宽松相称的区别,以及范例转换的规则。针对不同类型的范例值,如差别范例值、统一类的原始范例值和统一类的复合范例值,都给出了具体的比较方法。对于宽松相称的情况,也解释了原始范例值和对象之间的比较规则。通过本文的学习,读者可以更好地理解JavaScript中相称性推断的概念和应用。 ... [详细]
  • 本文介绍了闭包的定义和运转机制,重点解释了闭包如何能够接触外部函数的作用域中的变量。通过词法作用域的查找规则,闭包可以访问外部函数的作用域。同时还提到了闭包的作用和影响。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • 目录实现效果:实现环境实现方法一:基本思路主要代码JavaScript代码总结方法二主要代码总结方法三基本思路主要代码JavaScriptHTML总结实 ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • 如何使用Java获取服务器硬件信息和磁盘负载率
    本文介绍了使用Java编程语言获取服务器硬件信息和磁盘负载率的方法。首先在远程服务器上搭建一个支持服务端语言的HTTP服务,并获取服务器的磁盘信息,并将结果输出。然后在本地使用JS编写一个AJAX脚本,远程请求服务端的程序,得到结果并展示给用户。其中还介绍了如何提取硬盘序列号的方法。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • Android JSON基础,音视频开发进阶指南目录
    Array里面的对象数据是有序的,json字符串最外层是方括号的,方括号:[]解析jsonArray代码try{json字符串最外层是 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • 从零学Java(10)之方法详解,喷打野你真的没我6!
    本文介绍了从零学Java系列中的第10篇文章,详解了Java中的方法。同时讨论了打野过程中喷打野的影响,以及金色打野刀对经济的增加和线上队友经济的影响。指出喷打野会导致线上经济的消减和影响队伍的团结。 ... [详细]
  • 利用Visual Basic开发SAP接口程序初探的方法与原理
    本文介绍了利用Visual Basic开发SAP接口程序的方法与原理,以及SAP R/3系统的特点和二次开发平台ABAP的使用。通过程序接口自动读取SAP R/3的数据表或视图,在外部进行处理和利用水晶报表等工具生成符合中国人习惯的报表样式。具体介绍了RFC调用的原理和模型,并强调本文主要不讨论SAP R/3函数的开发,而是针对使用SAP的公司的非ABAP开发人员提供了初步的接口程序开发指导。 ... [详细]
  • javascript  – 概述在Firefox上无法正常工作
    我试图提出一些自定义大纲,以达到一些Web可访问性建议.但我不能用Firefox制作.这就是它在Chrome上的外观:而那个图标实际上是一个锚点.在Firefox上,它只概述了整个 ... [详细]
  • 不同优化算法的比较分析及实验验证
    本文介绍了神经网络优化中常用的优化方法,包括学习率调整和梯度估计修正,并通过实验验证了不同优化算法的效果。实验结果表明,Adam算法在综合考虑学习率调整和梯度估计修正方面表现较好。该研究对于优化神经网络的训练过程具有指导意义。 ... [详细]
author-avatar
死了才能爱_403
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有