昨天爷爷给我发了一段js代码和这段代码在爷爷自己开发的DJS上面运行后的结果,让我分别在Node、Chrome和Firefox上面运行一遍,并且相互比较结果。
代码如下:
//为了方便看清楚,我加了一些注释
var x = {Name:['lisi', 'wang'], Age:12};
var y = x.Name;
console.log( "1.第一次打印x和y:" );
console.log( x );
console.log( y );
console.log( "----------------------------------" );
x.Name = "World";
console.log( "2.修改x.name=‘World’后,再次打印x和y:" );
console.log( x );
console.log( y );
运行之后,我发现了一个问题:浏览器运行js代码,在console.log(某对象)时,控制台里面不点开对象详情所看到的第一层的对象信息是没有什么问题的,能正常展示数组的个数, 但是点开详情,看到的第二层数组详细信息并非对象当时的信息。
Chrome和Firefox结果图:
而node运行后结果图:
原因:
js 的对象是引用类型,每次使用对象时,都只是引用了对象在堆中的引用,当修改了 x.name 时候,也修改了堆中引用的 name,当 console.log(x)打印的是对象当时的快照信息,当展开对象时候,会去内存读对象的属性值。
WebKit的console.log并没有立即拍摄对象快照,相反,它只存储了一个指向对象的引用,然后在代码返回事件队列时才去拍摄快照。 —《JavaScript异步编程》
因此,console.log()应该是同步的,只不过浏览器出于性能优先的考虑有时候会给我们一种console.log 是异步的错觉。所以,建议大家以后调试代码不要只依赖console.log()输出,它可能会欺骗你的眼睛哦,最好加断点调整!!!
解决:
利用 JSON.stringify(object) 将对象序列化到一个字符串中,以强制执行一次“快照”。
最后附上Chrome(Firefox跟其相同所以省略)、Node以及DJS运行js代码后的结果对比图:
check8和check9的源码:
iCount ++; //8
console.log( "\nCheck:%d-->", iCount );
x = 13;
calc( x );
function calc(iP1) {
var y = 334;
console.log( y );
z = doCalc();
function doCalc() {
console.log( y );
return x * y;
}
}
iCount ++; //9
console.log( "\nCheck:%d-->", iCount );
x = 13;
calc( x );
function calc(iP1) {
console.log( w );
var y = 33;
var w = 'HOHO';
z = doCalc();
function doCalc() {
var v = 99;
console.log( y );
return x * y;
}
}
参考:
链接:https://www.jianshu.com/p/f7535d62acbd
链接:https://blog.csdn.net/qq_39903567/article/details/114585207