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

[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()

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

完结~ 午休一会~~~

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值