序言
Javascript(上面全称JS)当今世界里将正则表达式分成了三种:原始正则表达式与提及正则表达式。
现共计六种正则表达式:String、Number、Boolean、Null、Undefined、Object、Symbol(ES6)、Bigint(ES10)。
原始正则表达式:String、Number、Boolean、Null、Undefined、Symbol、Bigint。提及正则表达式:Object(Array、Function、Date、RegExp之类)。相同类别的存储形式:
原始正则表达式:原始正则表达式的值在缓存中占有一般来说大小不一,留存在栈缓存中。提及正则表达式:提及正则表达式的值是第一类,在栈缓存中而已保存第一类的表达式URL和第一类在堆缓存中的存储门牌号,其文本是留存中堆缓存中的。相同类别的复本形式:
原始正则表达式对原始正则表达式,从两个表达式复本到另两个表达式,而已很纯粹的表达式操作过程,二者是不能有甚么负面影响的。let a = 1;let b = a;a = 3;console.log(a, b); // 3 1拷贝标识符提及正则表达式而对提及正则表达式,从两个表达式复本到另两个表达式,本质是复本了第一类的存储门牌号,两个表达式最终都还是指向同两个第一类。let a = {name: 橙某人};let b = a;a.name = yd;console.log(a, b);let c = [1];let d = c;c[0] = 2;console.log(c, d);拷贝标识符所以本章我们要讲的厚薄复本针对是提及正则表达式,上面我们就来仔细瞧瞧看看吧。
浅复本 与 深复本
概念
为甚么存在浅复本与深复本?简单一句话:“防止父对象数据被篡改。”
浅复本:完成复本后可能存在彼此之间操作互相负面影响的就是浅复本。深复本:完成复本后彼此之间操作绝对不能有互相负面影响的就是深复本。浅复本
数组浅复本 – concat()、slice()let arr = [1, 2, 3];let newArr = arr.concat();newArr[0] = 20;console.log(arr, newArr); // [1, 2, 3] [20, 2, 3]let arr1 = [1, 2, 3];let newArr1 = arr1.slice();newArr1[0] = 20;console.log(arr1, newArr1); // [1, 2, 3] [20, 2, 3]拷贝标识符第一类浅复本function copy(object) { let o = {}; for(let key in object) { o[key] = object[key]; } return o;}let obj = {name: 橙某人};let newObj = copy(obj);newObj.name = YD;console.log(obj, newObj); // {name: “橙某人”} {name: “YD”}拷贝标识符懵了?上面不是说不是说不互相负面影响的就是深复本吗?小编欺骗你?咋会呢?不要着急。
我在上面留了个心眼,就是浅复本可能存在彼此之间操作互相负面影响,也就是说浅复本也可能存在不能互相负面影响的情况。
文字游戏?小编玩起了文字游戏?给我打。。。
害,我也没有办法,这两个概念就是怎么迷,如果纯粹考虑第一类只有一层深度且也而已普通的原始正则表达式值的话,那你说上面的例子是深复本,那我不反驳,哈哈。
但他们确实是浅复本啦,如果是如下多层第一类深度的话,就跑不了了。
// 数组let arr = [1, 2, [1]];let newArr = arr.concat();newArr[2][0] = 10;console.log(arr, newArr); // [1, 2, [10]] [1, 2, [10]]let arr1 = [1, 2, [1]];let newArr1 = arr1.slice();newArr1[2][0] = 10;console.log(arr1, newArr1); // [1, 2, [10]] [1, 2, [10]]// 第一类function copy(object) { let o = {}; for(let key in object) { o[key] = object[key]; } return o;}let obj = {name: 橙某人, hobby: {val: basketball}};let newObj = copy(obj);newObj.hobby.val = football;console.log(obj, newObj); // {name: 橙某人, hobby: {val: football}} {name: 橙某人, hobby: {val: football}}拷贝标识符第一类多层级浅复本就无法处理了,这种情况就需要深复本了。
深复本
深复本就不是简单的复本提及门牌号了,而是在堆中重新分配缓存,并且把源第一类的所有属性都进行新建复本,以保证深复本的第一类提及不包含任何原有第一类或第一类上的任何第一类属性,拷贝后的第一类与原本的第一类是完全隔离的。
JSON.parse()、JSON.stringify()
数组深复本 – JSON.parse()、JSON.stringify()let arr = [1, 2, [1]];let newArr = JSON.parse(JSON.stringify(arr));newArr[2][0] = 10;console.log(arr, newArr); // [1, 2, [1]] [1, 2, [10]]let arr1 = [1, 2, [1]];let newArr1 = JSON.parse(JSON.stringify(arr1));newArr1[2][0] = 10;console.log(arr1, newArr1); // [1, 2, [1]] [1, 2, [10]]拷贝标识符第一类深拷贝 – JSON.parse()、JSON.stringify()let obj = {name: 橙某人, hobby: {val: basketball}};let newObj = JSON.parse(JSON.stringify(obj));newObj.hobby.val = football;console.log(obj, newObj); // {name: “yd”, hobby: {val: basketball}} {name: “yd”, hobby: {val: football}}拷贝标识符利用JSON.parse()、JSON.stringify()是不是非常简单粗暴?哈哈,但是呢。简单就肯定有弊端了,如:
let arr = [() => {}, { b: () => {} }, new Date()];let newArr = JSON.parse(JSON.stringify(arr));console.log(newArr);let obj = {a: () => {}, b: new Date()};let newObj = JSON.parse(JSON.stringify(obj));console.log(newObj);拷贝标识符

可怕不?函数不见了?日期类别变成字符串?这就是弊端了,只能说且用且谨慎了。
递归
上面形式虽然比较简单方便,但用的时候还是要稍微想一下,省得被坑了。
上面我们就用递归来实现下深复本,其中的思路:在对属性值进行复本的时候我们先判断下一下它的类别,如果是第一类,我们就递归调用深复本函数,如果不是就直接复本过去,就怎么简单。
// 深复本函数function deepCopy(obj) { if (typeof obj !== object) return; let result = obj instanceof Array ? [] : {}; for (let key in obj) { if (obj.hasOwnProperty(key)) { result[key] = typeof obj[key] === object ? deepCopy(obj[key]) : obj[key]; } } return result;}拷贝标识符测试标识符。
// 数组let arr = [1, 2, [1]];let newArr = deepCopy(arr);newArr[2][0] = 10;console.log(arr, newArr); // [1, 2, [1]] [1, 2, [10]]let arr1 = [1, 2, [1]];let newArr1 = deepCopy(arr1);newArr1[2][0] = 10;console.log(arr1, newArr1); // [1, 2, [1]] [1, 2, [10]]// 第一类let obj = {name: yd, hobby: {val: basketball}};let newObj = deepCopy(obj);newObj.hobby.val = football;console.log(obj, newObj); // {name: “yd”, hobby: {val: basketball}} {name: “yd”, hobby: {val: football}}拷贝标识符然后我们来测试下那些特殊的函数、日期类别。
let arr = [() => {}, { b: () => {} }, new Date()];let newArr = deepCopy(arr);console.log(newArr);let obj = {a: () => {}, b: new Date()};let newObj = deepCopy(obj);console.log(newObj);拷贝标识符

根据上图我们发现,函数是没有问题的,还是保留下来了,但是日期就完蛋了,变了个空第一类,Why? 不要着急,是深复本函数deepCopy()出现了问题,我们改改。
function deepCopy(obj) { if (typeof obj !== object) return; let result = obj instanceof Array ? [] : {}; for (let key in obj) { if (obj.hasOwnProperty(key)) { result[key] = typeof obj[key] === object && !(obj[key] instanceof Date) ? deepCopy(obj[key]) : obj[key]; } } return result;}拷贝标识符

这下正常了,明白了吧?嘿嘿~ 不明白的自己悟吧,本章就差不多这种子啦,拜拜咯。(当然递归而已一种形式,网上一搜各种各样实现深复本的形式,绝对优雅,感兴趣可以慢慢研究一下。)