json遍历的本质是对树结构的访问,个人认为除了js中自带的数据结构外,每一个前端同学最需要掌握的两种数据结构就是链表与树,理解前者有利于了解作用域链和原型链相关概念,树结构在日常开发中处处可见,本文通过两个常见面试题来介绍JSON的遍历。
一、js中遍历对象的两种方式
- for in for in可遍历原型链上扩展的属性
- Object.keys(obj).forEach 只遍历自身属性
二、如何遍历json
// dfs遍历
const json = {
a: { b: { c: 1 } },
d: [1, 2],
}
function dfs(n) {
console.log(n)
Object.keys(n).forEach((key) => {
dfs(n[key])
})
}
dfs(json)
三、json深copy
我们可以想象是根据一个树结构,构建一个新的树,生成每一个节点,最后通过后续遍历再让其建立联系
function deepClone(obj={}) {
if(typeof obj !== 'object' || obj == null) return obj
const result = obj instanceof Array ? [] : {}
Object.keys(json).forEach(key=> {
result[key] = deepClone(json[key])
})
return result
}
四、json修改
// 转为驼峰
const obj = {
"user_list": [
{
"user_id": "1234",
"nick_name": "aaaa",
"friedns": {
"user_id": "2222",
"nick_name": "aaaa",
}
},
"userId": "1234",
"nick_name": "aaaa"
]
}
function dfs(node) {
if (node == null || typeof node !== 'object') return node
const result = Array.isArray(node) ? [] : {}
Object.keys(node).forEach((key) => {
const newKey = key.replace(/_([a-z])/, (v) => v[1].toUpperCase())
result[newKey] = dfs(node[key])
})
return result
}
五、根据虚拟dom构建真实dom
function createEle(vNode) {
if (vNode && vNode.tag == null) {
return document.createTextNode(vNode)
}
const ele = document.createElement(vNode.tag)
Object.keys(vNode.props).forEach((key) => {
if (key === 'style') {
Object.keys(vNode.props.style).forEach((property) => {
ele.style[property] = vNode.props.style[property]
})
}else {
ele.setAttribute(key, vNode.props[key])
}
})
vNode.children.forEach((node) => {
ele.appendChild(createEle(node))
})
return ele
}
后记
树相关的操作,依赖递归,因为几乎树所有的操作都是需要对其进行遍历的,但可喜的是树的相关操作存在及强的模式化、大部分都围绕着dfs,回溯查找、分治,以及今天我们学习的树的copy。掌握这四类通用模版后就可以解决大部分树结构问题。