开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 5 天,点击查看活动详情
起因
偶然从朋友那里听说,互联网寒冬的严峻格局,让躺平的我后脊发凉,近些年随着互联网的兴起,大部分年轻人涌入了进来,造成了供大于求的现象,领先企业直接让新小企业无法存活。
立个flag,好好学习
感觉未来两年情况愈加复杂,还是要自己学习一个生存本领吧
开始
写一个深拷贝的例子吧,这个问题很久前就深入研究过。当时研究了两个方向,深度优先和广度优先。所以可以轻松写下了一个,这个应该是属于深度优先吧。 标准答案,还需要在for循环里判断一下 obj.hasOwnProperty(key) ,判断一下这个key是不是自身的属性。for in 遍历的不仅有自身属性,还有继承的属性
// 深拷贝
function copy (obj) {
if (typeof obj !== 'object') {
return obj
}
let o = {}
if (Array.isArray(obj)) {
o = []
}
for (let key in obj) {
o[key] = copy(obj[key])
}
return o
}
let obj = {
name: "tom",
child: {
name: "www",
},
aa: [1, 3, { name: 't' }]
}
let o = copy(obj)
console.log(o)
如果考虑到属性中包含函数和属性中有相同引用时,上面的方式显然是经不起推敲的,只是入门级的深考呗,只是为了完成任务而完成, 有如下数据
function xxx () {
console.log('xxx')
}
let s = {
o: 'jjjj'
}
let obj = {
name: "tom",
child: {
name: "www",
},
d: { o: 'jjjj' },
b: s,
c: s,
a () {
console.log('obj')
},
f1: xxx,
f2: xxx,
aa: [1, 3, { name: 't' }]
}
显然拷贝出来的数据属性b和属性c并不是同一个引用。那么怎么复用这种引用关系呢?就是要将已经处理的数据缓存起来。利用weakMap的特性,将对象obj,当key然后,处理结果当成value,如果下次遇到同样的属性,就直接复用之前拷贝的对象,这样才实现了真正意义结构上的拷贝
// 深度优先拷贝
function copy (obj, visited = new WeakMap()) {
if (visited.has(obj)) {
return visited.get(obj)
}
// 此处
if (typeof obj !== 'object') {
return obj
}
let o = {}
if (Array.isArray(obj)) {
o = []
}
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
o[key] = copy(obj[key], visited)
visited.set(obj, o)
}
}
return o
}
函数的处理,讲道理,我是不认为需要特殊处理函数的,因为函数本身就应该是纯函数,直接指向原来的函数也无所谓,复制函数很麻烦也很危险。此处忽略
if (typeof obj === 'function') {
let res
let str = obj.toString()
if (str.includes('function')) {
res = eval(`(${str})`)
} else {
res = eval(`(function ${str})`)
}
visited.set(obj, res)
return res
}
广度优先
广度优先
结论
深度优先算法占用内存少,但是速度较慢,广度优先算法占用内存多,速度较快