浏览器在控制台打印对象内容时候顺序不是按照我们书写的顺序显示
今日使用递归方法进行深拷贝时候,偶然发现浏览器在控制台打印对象内容时候顺序不是按照我们书写的顺序显示,于是进行一番深究。最终发现了其显示的规律(规则)。
不过该问题可能很多人刚学习js的就发现了,可能只是没有过多关注。
下面介绍一下我探索的过程 (若是刚开始学习js看到的本文,可以直接跳到最后看总结)=>
先看这一段使用函数递归方法进行深拷贝的代码,
const obj = {
age: 17,
name: '路飞',
hobby: ['吃肉', '冒险'],
family: {
grandfather: '蒙奇 D 卡普',
father: '蒙奇 D 龙',
},
}
function deepCopy(newObj, oldObj) {
for (let k in oldObj) {
if (oldObj[k] instanceof Array) {
//如果克隆对象是“数组”
newObj[k] = []
deepCopy(newObj[k], oldObj[k])
} else if (oldObj[k] instanceof Object) {
//如果克隆对象是“对象”
//先判断数组再判断数组,因为
//console.log(Array instanceof Object) 结果是true
newObj[k] = {}
deepCopy(newObj[k], oldObj[k])
} else {
newObj[k] = oldObj[k]
}
}
}
我们在控制台打印一下 =>
const luffy = {} //定义一个空对象用来copy
deepCopy(luffy, obj) //调用深拷贝函数
luffy.age = 19 //修改拷贝过来的数据
luffy.hobby[0] = '吃蔬菜' //修改拷贝过来的深层数据
console.log(obj);
console.log(luffy)
看一下结果 =>
并没有什么问题对吧?输出结果也符合我们的预期。但是你们有没有注意到,我们定义对象时候是按照age、name、hobby、family顺序进行的。但是输出的顺序却是age、family、hobby、name。
这个情况显然是不符合我们输出结果的预期的,尽管对于正确性并没有影响,但是这个输出结果的顺序我们还是有必要去探索一下。刚开始我以为是for in 循环的原因,于是查看了官方文档,官方文档的原话是:for...in
语句以任意顺序迭代一个对象的除Symbol以外的可枚举属性,包括继承的可枚举属性。
任意顺序?这是什么意思,我们去代码里测试一下就好了,我们在for in 中加上这样一句代码,让其每次遍历时候,都把当前对象的值给打印在控制台,这样我们就能看到他的遍历顺序=>
console.log(oldObj[k])
看控制台打印结果=>
欸?遍历顺序确实是我们定义对象中键值对的顺序,但是为什么在最后的显示结果中顺序却不同?我百思不得其解。
于是在网上查找资料,看到一则相关的博客的说法是和浏览器有关,不同的浏览器使用for in遍历顺序会不同,于是我便切换到edge浏览器测试=>
可以看到edge的输出顺序与谷歌浏览器相同,看来for in循环并不是引起打印顺序不同的根本原因。我们在obj对象中增加几条测试数据 =>
const obj = {
gender:'男',
age: 17,
name: '路飞',
hobby: ['吃肉', '冒险'],
skill:'橡胶',
family: {
grandfather: '蒙奇 D 卡普',
father: '蒙奇 D 龙',
},
dream:'ONE PIECE',
}
我们新增了gender、skill、dream属性。来看打印结果=>
欸?我们可以看到,这个输出结果又发生了变化,怪哉怪哉,于是我尝试找出顺序的前后规律。经过仔细观察,发现这个顺序居然是按英文字母a-z来进行排列的。
于是我大胆进行猜想===>这可能不是按照英文字母a-z顺序来排列,而是按照ASCII表的值来进行排列的!!!
有关ASCII表的知识,请点击以下链接进行查看:
于是再次进行测试=>
const obj = {
0:'testOne',
A:'testTwo',
y:'testThree',
gender: '男',
age: 17,
name: '路飞',
hobby: ['吃肉', '冒险'],
skill: '橡胶',
family: {
grandfather: '蒙奇 D 卡普',
father: '蒙奇 D 龙',
},
dream: 'ONE PIECE'
}
按照上述猜想,输出结果顺序应该是0、A、age、dream、family、gender、hobby、name、skill、y
我们查看输出结果=>
果然和我们预测的丝毫不差。看来控制台在显示"对象"数据类型的时候,是按照ASCII表的数值来进行显示。不过经过测试这仅仅是对象在控制台的显示层面,并不会影响到计算过程。但是在查找资料过程中确实看到了有关于for in遍历顺序的问题,有兴趣者请点击下方链接查看:
总结:浏览器在控制台显示"对象"数据类型的时候,是按照ASCII表的数值来进行显示。不过这并不会影响到你的计算,只是控制台显示层面。