关于JS中, 对引用类型console出现偏差的问题分析

2020/04/15 JavaScript 共 769 字,约 3 分钟

key 引用类型 内存 同步执行 console.log

console.log

Q :

console.log 打印的时候,a 里面是有一个元素,但打印后展开,a 有两个值

A :

首先,我们要明白,数组是一个引用类型,即,变量名只是指向内存地址的指针

其次,在上图中,我们是先声明一个 变量 a,指向一个数组[1],随后进行打印,再接着是对数组进行 push 操作。OK,潜意识里,我们认为 js 是单进程且顺序执行,并且代码块中都是同步的,所以我们会觉得打印出来是 push 操作之前的数组,但实际上,显示 Array 的长度是 1,当我们查看元素, 反而是 push 后的,出现了偏差。

这是为什么呢? 让我们思考加探索一下。

Music,Let’s go

  • 上面我们指出,数组是引用类型,变量是个指针指向内存地址,数组的 push 操作,是在一段连续的内存上增加一个值
  • 由于都是同步语句,那么就顺序执行。在 console 的时候,显示数组长度 1
  • console 在打印的时候,确实是 Array(1), 紧接着该变量指针 数组执行了 push 操作, 这时候代码块已经执行完.
  • 但在随后查看的时候元素却是两个, 显示出了偏差 !
  • 这里为什么出现了显示不一致的情况?
  • 原来, console 打印引用类型的操作, 是先打印引用类型的快照, 在展开对象的时候, 会再次去读取变量指针的值, 而此时, 代码块已经执行完了, 即 push 操作已经生效, 变量指针指向的值已经更改, 所以读取的是 push 操作后的值. 所以出现了 Array(1), [0: 1, 1: 2] 的情况。

事实是如此吗, 我们简单验证一下

console.log 的时候, 顺便打印 key, ( 因为数组也是对象, 所以可以 keys)

console.log

使用断点验证

console.log

在使用断点后, 第一次打印的数据, 展开后是 push 操作前的值, 代码块执行完后, 再次展开还是一个元素.

上面两种方式, 说明了 console 操作对于引用类型, 是有两次读取的. 第二次来自首次展开对象.

文档信息

Search

    Table of Contents