为什么console.log在修改二维数组之前就输出修改后的值?

本文讲解JavaScript中修改数组中的数据与console.log问题。

背景

今天写DP,console.log 打印二维数组,发现无论是修改前打印还是修改后打印都是一样的。

arr = [[1,2,3,4,5],[6,7,8,9,10],[11,12,13,14,15],[16,17,18,19,20]];
console.log(arr);
arr[0][0] = 999; arr[1][1] = 999; arr[2][2] = 999; arr[3][4] = 999;
console.log(arr);

FirstError

为什么会出现这种现象?如果我非要看修改前的,怎么看?最后有例子

预备知识

console.log 对于六种基本类型是直接输出,对于引用类型是打印引用的快照

且当有多层时,不会展开多层,而是保存第二层的引用,当你点击展开时才去读取内容。

分析

chrome devtools 会默认预览下一层。

注意“加载、展开、预览”的区别

加载:从内存中加载数据

展开:单击按钮展开数据

预览:未展开时看到的数据

初始是不展开任何层,但预览第一层。

当你点第一个展开键(三角形)时,加载第一层的内容,展开的是第一层,预览第二层(无第二层则只展开第一层)。但因为 chrome devtools 有缓存,即使展开看到修改后的内容,但预览不会变。

点击第二个展开键,加载第二层,展开第二层,预览第三层(没有则只展开第二层)。多层同理。

若想看到未修改的所有内容

若想看到未修改的所有内容,则要在修改语句执行之前就展开后续层级,这时候 chrome devtools 就会输出未修改的内容,可以用 setTImeout 验证,在 setTImeout 的延时函数执行前展开后续层级。

如果是修改语句执行结束了,再去展开,就是修改后的内容。

关闭再展开并不会重新读取内容。

关闭再展开并不会重新读取内容。当 setTimeout 的延迟函数执行前展开所有,会看到未修改的所有内容,预览和展开都正确。当 setTImeoout 执行完后关闭再展开(此时已修改),输出依然不变,依然是修改前的内容,因为已经加载过了就不重新读取了。

怎么解决

虽然 setTimeoout 可以用,但并不是最优解。毕竟每次都要赶时间去展开所有层级。

JSON化

先将对象(二维数组也是对象)转换成json字符串再解析一次。 JSON.parse(JSON.stringify(xxx))

JSON.stringify()

将JavaScript对象或值转换为json字符串

JSON.paarse()

解析json字符串

深拷贝

对每个层级进行一次深拷贝。但这不是明智的做法。

代码演示

const testAny = () => {
		oneArr = [1,2,3];
		twoArr = [[4,5,6],[7,8,9]];
		oneObj = {"a":true,"b":10};
		twoObj = {"a":true,"b":20,"c":{"d":true,"e":"对象中的字符串1"}};
		str = "字符串1";
		num = 1;
		console.log("修改前的普通输出"); // 修改前的普通输出
		console.log(oneArr,twoArr,oneObj,twoObj,str,num);
		console.log("修改前经过json化的输出");// 修改前经过json化的输出
		console.log(JSON.parse(JSON.stringify(oneArr)),JSON.parse(JSON.stringify(twoArr)),JSON.parse(JSON.stringify(oneObj)),JSON.parse(JSON.stringify(twoObj)),JSON.parse(JSON.stringify(str)),JSON.parse(JSON.stringify(num)));

		setTimeout(()=>{
			oneArr[1] = 999;
			twoArr[0][2] = 999, twoArr[1][2] = 999;
			oneObj.a = false,oneObj.b = 30;
			twoObj.a = false,twoObj.b = 40, twoObj.c.d=false, twoObj.c.e="对象中的字符串2";
			str = "字符串2"
			num = 999;
			console.log("修改后的普通输出"); // 修改后的普通输出
			console.log(oneArr,twoArr,oneObj,twoObj,str,num);
		},5000);


	}
	testAny();

LastTest
附录

参考

  1. Js中修改数组中的数据与console.log问题

  2. 问题记录:console.log在对象修改前打印出对象修改后的值

  3. How can I make console.log show the current state of an object? StackOverflow2011年问答

  4. Why does console.log output modified values even before they have been modified?

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值