事情是在最近的一次开发中发现一个诡异的问题,前端在操做某个对象时,发如今chrome下console出来的值和预期的结果不一致,而后就debugger看了一下却发现结果是对的。屡次验证后发现debugger和console的值不一致,因而小小的探索了一番。
很少说上代码:javascript
var obj = [{ 1: 1 }, { 2: 2 }, { 3: 3 }, { 4: 4 }]
console.log(obj)
obj.shift()
console.log(obj)
按照正常理解,你确定会以为what? 这么简单的code能有什么问题?我猜你会说结果是这样
//第一个console [{ 1: 1 }, { 2: 2 }, { 3: 3 }, { 4: 4 }]
//第二个console [{ 2: 2 }, { 3: 3 }, { 4: 4 }]复制代码
一切彷佛都在乎料之中,却又每每超乎寻常,那咱们来看看实际的效果吧
前端
what?本切图仔多年的切图经验失效了???js的执行不是同步的?代码的执行顺序不是从右到左,从上到下????java
一时间有点没有头绪。那么先打个debugger看看吧。chrome
结果以下:segmentfault
结果一切正常。因而陷入懵逼状态。。。。。数组
懵了2s,而后开始寻找问题根源,在确认代码没有写错,浏览器没有缓存等问题后开始尝试以下:浏览器
const obj = [{ 1: 1 }, { 2: 2 }, { 3: 3 }, { 4: 4 }]
console.log(obj)
obj.shift()
console.log(obj)
复制代码
const obj = [1, 2, 3, 4]
console.log(obj)
obj.shift()
console.log(obj)复制代码
控制台输出:
缓存
console出来的结果也对了,那么基本能够肯定问题是出在数据类型上。并且基本数据类型是OK的,那么就是复合数据类型的问题了。联想到复合数据类型的引用属于地址引用,开始设想是地址引用形成了数据污染的问题,开始继续尝试bash
const obj = [{ 1: 1 }, { 2: 2 }, { 3: 3 }, { 4: 4 }]
const obj1 = obj.slice(0)
console.log(obj1)
obj.shift()
console.log(obj)复制代码
控制台输出:异步
结果彷佛是跟想象中的差差差差很少吧,但又感受哪里怪怪的。继续尝试
const obj = [{ 1: 1 }, { 2: 2 }, { 3: 3 }, { 4: 4 }]
console.log(JSON.stringify(obj))
obj.shift()
console.log(JSON.stringify(obj))复制代码
控制台输出:
输出的结果是对了,貌似仍是有点麻烦。
经过几回尝试,大体确认了问题所在,开始寻找问题的根源。
功夫不负有心人,好歹是面向搜索引擎的切图仔,貌似找到了一丢丢线索:
资料来源:segmentfault.com/a/119000001…
如下内容彻底引自:《你不知道的javascript中卷》第二部分异步和性能 1.1 异步控制台部分
并无什么规范或一组需求指定console.* 方法族如何工做——它们并非JavaScript 正式的一部分,
而是由宿主环境(请参考本书的“类型和语法”部分)添加到JavaScript 中的。所以,不一样的浏览器和JavaScript
环境能够按照本身的意愿来实现,有时候这会引发混淆。尤为要提出的是,在某些条件下,某些浏览器的console.log(..)
并不会把传入的内容当即输出。出现这种状况的主要缘由是,在许多程序(不仅是JavaScript)中,I/O 是很是
低速的阻塞部分。因此,(从页面/UI 的角度来讲)浏览器在后台异步处理控制台I/O 可以提升性能,这时用户甚
至可能根本意识不到其发生。
书中建议:
若是遇到这种少见的状况,最好的选择是在JavaScript 调试器中使用断点,而不要依赖控制台输出。次优的方案
是把对象序列化到一个字符串中,以强制执行一次“快照”,好比经过JSON.stringify(..)
复制代码
结论:经过一次诡异的问题,发现了一个以前不多注意到的一个点。吃一堑长一智,日常开发中仍是要多注意,遇到问题了要细心调试查找,虽然可能暂时一头雾水,可是探索的过程才是乐趣所在啊。