- js 基本概念———— 数据类型
- js 深浅拷贝之概念
- 代码实现 —— 数组和对象的j浅拷贝
- 代码实现 —— 数组和对象的深拷贝
参考链接:
https://www.jianshu.com/p/ec47faea0a58
https://juejin.im/post/5b5affaef265da0f86543bc9
1. js数据类型:
js数据类型共有七种,number/string/boolean/null/undefined/广义含义的object/symbol(ES6新增类型),这里对于symbol数据不做解释,以上数据类型可分为简单数据类型和复杂的数据类型.
- 简单的数据类型:number/string/boolean/null/undefined.
- 复杂数据类型: 广义含义的object又可分为object对象,array数组,function函数
2. 概念 —— Clone
- js数据的赋值和传递时简单的数据类型是传值传递(pass by value),而复杂类型的数据传址传递(pass by value),简单的数据类型只会存在Stack栈内存中,内存消耗较低。而复杂类型的数据内容量都比较庞大,通常是在stack栈内存中存储引用变量(简单来说就是Heap是堆内存的地址),在堆内存中存储引用的实例(了解Stack 和Heap中变量的存储实际情况),这就是简单数据类型和复杂数据类型 的最大区别,主要表现在复制的时候。而深浅拷贝只在复杂类型(又叫引用类型)数据中有的数据概念。
2.1 浅拷贝shallow copy:只复制某个object的引用值,不会改变heap内存的实例。浅拷贝之后各个值的引用地址指向同一个堆内存,所以只要改变一个实例另外一个对象也会跟着改变。
2.2 深拷贝deep copy :复制并创建一个一摸一样的对象(既有栈内存中的引用值又有堆内存中的对象实例),而且不共享对象,对新的对象进行操作不会改变之前的对象。
3. 代码示例
3.1 浅拷贝
- 封装一个函数对于对象进行浅拷贝
var obj = {name :"qinglin", age : 18, gender : "male"};
function cop(obj){
var newObj = {};
for(var key in obj){
newObj[key] = obj[key]
}
return newObj
}
var obj2 = cop(obj);
obj2.name = "yy";
console.log(obj.name)
-
浅拷贝对象
var obj1 = {name:"qq"} ; var obj2 = obj1 ; obj2.name = "yy" console.log(obj1.name) //yy console.log(obj2.name) //yy
-
浅拷贝数组
var arr1 = ["a","b","c"]; var arr2 = arr1; arr2[4] = "qinglin" console.log(arr1) // ["a", "b", "c", empty, "qinglin"]
3.2 实现深拷贝的四种种方法
-
数组的slice() concat() 方法实现深拷贝 ————— 该方法存在缺点,只能对没有引用变量的数组进行深拷贝,不会改变原数组。
slice()方法:
var arr = ["a","b","c","d","e"]; var arrcop = arr.slice(0); arrcop[5] = "gg"; console.log(arr) console.log(arrcop)
concat()方法:
var arr = ["a","b","c","d","e"]; var arrcop = arr.concat(["cop1","cop2"]); console.log(arr) console.log(arrcop)
-
ES6扩展运算符实现深拷贝
var arr = ["2","4","6","8"]; var [...arr2] = arr; arr2.push ("ahhah") console.log(arr) console.log(arr2)
-
对象引用作为函数参数,通过递归方法实现深拷贝
function deepCopyObj(obj){ if(typeof(obj) !== "object" || obj === null) return obj; if(obj instanceof(Array)){ newArr = []; for(var i=0;i<obj.length;i++){ if(typeof(obj[i]) === "object" && obj[i] !== null){ newArr[i] = argumenrts.Array.prototype.slice.call(obj[i]); }else{ newArr[i] = obj[i] } } }else{ newArr = [] for(i in obj){ if(typeof(obj[i]) === "object" && obj[i] !== null){ newArr[i] = obj[i] }else{ newArr[i] = obj[i] } } return newArr; }
}
-
通过js对象和JSON字符串之间的转换来实现深拷贝
//这种方法只对number/string/boolean/array/object/扁平化对象等能够被JSON数据直接表示的数据类型适用。 var obj1 = {qinglin:{age:18}}; var obj2 = JSON.parse(JSON.stringify(obj1)) ; obj2.qinglin.gender = "male"; console.log(obj1) console.log(obj2) //对于function 等类型数据该深拷贝方法不适用,会丢失不能表示的数据 var originObj = { name:"qinglin", age:18 , gender:"male", hobby:function(){alert("Say Hello !")} } var cloneObj = JSON.parse(JSON.stringify(originObj)); console.log(originObj); //{name: "qinglin", age: 18, gender: "male", hobby: ƒ} console.log(cloneObj); //{name: "qinglin", age: 18, gender: "male"}