console.log顺序调用却输出异常?Matrix3D日志重复问题求助
问题分析与解决
先给你吃个定心丸:这和JS线程半毛钱关系都没有!JS是单线程同步执行的,你的代码绝对是按顺序一步步跑的:
- 创建
m1这个Matrix3D实例 - 执行
initRotX(20)把m1改成X轴旋转后的状态 - 执行
console.log(m1) - 执行
initRotY(20)把m1改成Y轴旋转后的状态 - 执行
console.log(m1)
那为啥两次控制台输出看起来都是Y轴旋转后的矩阵?核心锅在浏览器控制台的“延迟求值”特性:
当你用console.log打印对象(比如你的Matrix3D实例)时,控制台并不会立刻把对象的所有属性拍个快照显示出来,而是只存了一个指向这个对象的引用。等你在控制台里点开这个对象看详情的时候,它才会去读这个对象当前的状态——这时候m1早已经被initRotY(20)改完了,所以两次点开看到的都是最终的Y轴旋转矩阵。
而你每次新建Matrix3D实例的时候,每个实例都是独立的“个体”,后续修改新实例不会影响旧的,所以控制台点开时能看到各自的状态,自然就正常了。
怎么验证这个结论?
你可以用下面两种方式打印,就能看到对象的即时状态了:
- 把对象转成字符串(字符串是值类型,不会跟着原对象变):
m1 = new Matrix3D(null); m1.initRotX(20); console.log(JSON.stringify(m1)); // 这里会输出X旋转后的矩阵字符串 m1.initRotY(20); console.log(JSON.stringify(m1)); // 这里会输出Y旋转后的矩阵字符串 - 先复制一份对象再打印:
m1 = new Matrix3D(null); m1.initRotX(20); console.log(Object.assign({}, m1)); // 打印X旋转状态的副本 m1.initRotY(20); console.log(Object.assign({}, m1)); // 打印Y旋转状态的副本
试一下就知道,两次打印的结果完全不一样了。
总结
说白了就是浏览器控制台的显示机制给你造成了“视觉错觉”,不是代码执行顺序或者线程的问题。如果要在控制台看对象的即时状态,记得用上面的快照方式打印哦。
内容的提问来源于stack exchange,提问作者user9648914
相关产品推荐
相关产品推荐

