1、JS包含两种数据类型: 值类型(基本类型)和引用类型(对象类型)
值类型都是简单的数据段(Number、String 、Boolean、Null、Undefined),引用类型是由多个值构成对象(Object 、Array 、Function 、Data等)。
我们进行变量赋值时,解析器首先要确认的就是这个值是基本类型还是引用类型。
值类型数据存储在栈(stack)中,栈是内存中一种特殊的数据结构,也称为线性表。变量的位置和变量值的位置是重叠的,也就是说值类型的数据被存储在变量被访问的位置。
引用类型数据存储在堆(heap)中,堆是内存中的动态区域,相当于自留空间,在程序运行期间会动态分配给代码。堆中存储的一般都是对象,然后通过一个编号传递给栈内变量,这个编号就是所谓的引用指针(point),这样变量和变量值之间是分离的,它们通过指针相联系。当读写数据时,计算机通过变量的指针找到堆中的数据块,并进行操作。
2、对象的浅拷贝
浅拷贝就是增加一个引用指针(point)指向已存在的内存,浅拷贝只是拷贝了内存的地址,原来的变量跟拷贝出来的变量指向同一内存地址,改变其中某个变量,另一个也会变。
let arr1 = [1,2,3]; let arr2 = arr1; arr1.push(4); console.log(arr1); // [1,2,3,4] console.log(arr2); // [1,2,3,4]
3、深拷贝
深拷贝就是增加一个引用指针(point),并申请一个新的内存,并且让这个新增加的“指针”指向这个新的内存地址,当我们需要复制原对象而又不能修改原对象的时候,深拷贝是唯一的选择。
3、深拷贝的方法
黑科技手段。会忽略值为function以及undefied的字段,而且对date类型的支持也不太友好,只能克隆原始对象自身的值,不能克隆它继承的值。
JSON.parse(JSON.stringify(obj))
递归
function clone(value, isDeep) { if (value === null) return null if (typeof value !== ‘object‘) return value if (Array.isArray(value)) { if (isDeep) { return value.map(item => clone(item, true)) } return [].concat(value) } else { if (isDeep) { var obj = {} Object.keys(value).forEach(item => { obj[item] = clone(value[item], true) }) return obj } return { ...value } } } var objects = { c: { ‘a‘: 1, e: [1, {f: 2}] }, d: { ‘b‘: 2 } } var shallow = clone(objects, true) console.log(shallow.c.e[1]) // { f: 2 } console.log(shallow.c === objects.c) // false console.log(shallow.d === objects.d) // false console.log(shallow === objects) // false
递归改造(保持原形链的继承)
var clone = function (obj) { if(obj === null) return null if(typeof obj !== ‘object‘) return obj; if(obj.constructor===Date) return new Date(obj); if(obj.constructor === RegExp) return new RegExp(obj); var newObj = new obj.constructor (); //保持继承链 for (var key in obj) { if (obj.hasOwnProperty(key)) { //不遍历其原型链上的属性 var val = obj[key]; newObj[key] = typeof val === ‘object‘ ? arguments.callee(val) : val; // 使用arguments.callee解除与函数名的耦合 } } return newObj; };
原文地址:https://www.cnblogs.com/stronggirlyao/p/9803597.html