关于前端:小白手写深拷贝的学习过程

37次阅读

共计 1744 个字符,预计需要花费 5 分钟才能阅读完成。

Today,逛 segmentfault 的时候,看到有很多大神手写了深拷贝,记得也有大厂把这个当作题目,那我也来学习一下吧~
在此之前,我都是间接 JSON.parse(JSON.stringfy())实现深拷贝。有时写业务时,遇到一些谬误应用深拷贝就能解决。有一段时间,我居然认为 ”…[]” 这种就是对数组进行深拷贝了 ….. 总之这块常识把握得不够。
开始撸码!首先理解下,浅拷贝和深拷贝的含意。

以前的认知 当初的认知
浅拷贝是 间接赋值 ,不仅把值赋了, 援用也雷同——比方浅拷贝对象 a 到 b,如果批改 a 外面的某个属性,b 里对应的属性也会变更。 浅拷贝 只能赋值最外一层,比方对象 obj1={a:{a:{a:1}}}, 浅拷贝给 obj2,批改 obj1.b=2,再批改 obj1.b.b=2; 输入 ob2 为{a:{a:{a:1}},b:2}。obj2.b 不是对象。
能够应用 JSON.parse(JSON.stringfy()) 实现,而且根本够用写业务了呢,或者依赖 lodash 的 _.cloneDeep() 实现。 手写
没遇到转换失败的场景 JSON.parse(JSON.stringfy())有毛病:1、undefined 转换会间接隐没;2、RegExp 转换后变成{};3、NaN、+-Infinity 转换后变成 null;4、环援用会报错:TypeError: Converting circular structure to JSON

我跟着 https://segmentfault.com/a/11… 这篇文章,一起手动写了下代码。写到最初都挺好,也实现了性能。在此过程中,学到了很多常识——

1、根底类型和援用类型别离有哪些?
根底类型:String Number Boolean Undefined Null
可循环的援用类型:Array Object Map Set
不可循环的援用类型:Symbol RegExp Function

2、判断类型的办法?

Object.prototype.toString.call(x)

3、递归写法?

function digui(sum) {if(sum==0){return 0;}
    return sum+digui(sum-1)
}
console.log(digui(6));

4、拷贝 Symbol 的办法?

Object(Symbol.prototype.valueOf.call(x));

5、for…in 和 for…of 的区别

for…in for…of
举荐遍历对象——对象的键名,遍历数组——数组的索引(即键名);枚举属性,包含原型 举荐遍历数组——元素值;遍历对象,不蕴含可枚举属性

6、环援用是什么意思?如何解决它的深拷贝?
环援用就是 value 是变量本人,能够应用 Map 解决。具体解决见文章里所说。

另外还学习到了如何拷贝函数、Symbol、RegExp,Map、Set。不过,也有不了解的中央:
思考 1、76 行代码(见图一)是判断援用数据类型,通过输入,看进去返回的 temp 是 origin 的雷同类型的空值,比方 origin 是 {key:origin},那 temp 就是{}。这时 map 曾经保留了 key 为 origin,value 为{} 的值——这不就不对了嘛?环援用就变成了 {}(见图三)。起初,我把 origin 只保留了一个换援用而后 debugger 一步步走下来,发现递归走了两次,第一次执行了 map.set,走到第 100 行代码(见图四),把换援用作为 key 又循环了一次,因为第一次的 map.set,所以 79 行代码(见图一)的 if 判断能够通过,从而设置了环援用的值。

图一

图二

图三

图四

7、Map 如何获取值和赋值?

var map= new Map();
map.get('key');
map.set('key','value');

8、Set 是什么?Set 如何获取值和赋值?
set 相似数组,但值惟一

var set = new Set()
set.add(1)
set.delete(2)
set.has(1) ---> true/false
set.size
set.clear()

9、如何拷贝函数?
思路:函数 toString, 应用正则找到函数体和参数,返回 new Function(参数, 函数体)

10、如何拷贝 RegExp?
这个没看懂,等前面看懂了补充把

正文完
 0