数据类型
数据类型分为基本数据类型和引用数据类型
基本数据类型
-
六种:Number(数值)、string(字符)、undefined、null、symbol、Boolean(布尔类型)
-
存储位置:存放在栈中,使用完之后就会被销毁;数据大小确定,内存空间大小可以分配,它们是直接按值存放的,所以可以直接按值访问
-
eg:
var a = 10; var b = a; b = 20; console.log(a); // 10值 console.log(b); // 20值
引用类型
-
三种:object(对象)、array(数组)、function(函数);严格意义上就一种,即对象,因为数组函数都是对象
-
存储位置:属性名存放在栈中,属性值存放在堆中,使用完之后不会销毁,而是垃圾回收机制将其回收
-
eg:
var obj = {name:'yaxi'}; var obj1 = obj; obj1.name = 'shuyan';
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KgDoPEut-1595855961175)(前复制以及深复制.assets/image-20200727210623804.png)]
浅复制
只是拷贝了基本类型的数据,而引用类型数据,复制后也是会发生引用,我们把这种拷贝叫做“(浅复制)浅拷贝”,换句话说,浅复制仅仅是指向被复制的内存地址,如果原地址中对象被改变了,那么浅复制出来的对象也会相应改变。
特点
总结浅拷贝的规律:
1、当第一层为基本数据类型时,改变不会使原始数据一同改变
2、当原始数据中包含子对象时改变会时原数据一同改变
3、既然属性值类型是数组和或象时只会传址
实现浅拷贝的方式
for…in
-
for…in只循环第一层
let obj = { name: 'hong', arr: ['a', 'b', 'c'], 'name': 'yaxi', obj1: { key: 'yaxi' } } function shalLowCopy(obj) { var newObj = Array.isArray(obj) ? [] : {}; //for...in只循环第一层 for (const i in obj) { if (obj.hasOwnProperty(i)) { newObj[i] = obj[i]; } } return newObj; } let newObj = shalLowCopy(obj); console.log("----------------------------对象的浅复制----------------------------"); console.log(newObj); newObj.arr[1] = '1'; newObj.obj1.key = 'shuyan1'; newObj.name = 'green'; newObj.arr = ['1', '2']; newObj.obj1 = { key: 'shuyan2' }; //相当于在新对象中新建了一个与原始对象子对象同名的对象,所以在新对象中会使用新创建的子对象,但是对原始对象的子对象没有影响 newObj.obj1.key = 'shuyan3'; console.log(obj); console.log(newObj); //数组 let arr = ['1', '2', '3', [ '4', '5', '6' ]]; let newArr = shalLowCopy(arr); console.log("----------------------------数组的浅复制----------------------------"); console.log(newArr); newArr[2] = '4'; newArr[3][1] = '10'; console.log(arr); console.log(newArr);
object.assign()
-
用es6中的方法object.assign()实现浅复制 特点:浅拷贝、对象属性的合并
/** * var nObj = Object.assign({},obj,obj1); * 解析:花括号叫目标对象,后面的obj、obj1是源对象。 * 对象合并是指:将源对象里面的属性添加到目标对象中去,若两者的属性名有冲突,后面的将会覆盖前面的 */ let newAssign = Array.isArray(obj) ? [] : {}; Object.assign(newAssign, obj); console.log("----------------------------es6新方法object.assgin()的浅复制----------------------------"); console.log(newAssign); newAssign.name = 'hongshuyan'; newAssign.obj1.key = 'shuyan2'; console.log(obj, newAssign)
深拷贝
通俗一点理解就是浅拷贝出来的数据并不独立,如果被复制的对象改变了,那么浅拷贝的对象也会改变,深拷贝之后就会完全独立,与浅拷贝断绝关系。
实现深拷贝的方法
使用for…in 用递归
- 深拷贝:对象中所有子对象都会被遍历完全 方法一:使用for…in方法实现遍历和复制,其中子对象使用递归
function shalHighCopy(obj) {
let newObj = Array.isArray(obj) ? [] : {};
if (obj && typeof obj === 'object') {
for (let i in obj) {
if (obj.hasOwnProperty(i)) {
if (obj[i] && typeof(obj[i]) === 'object') {
//如果对象的属性值为object的时候,递归调用shalHighCopy,即再把子对象复制一份到新的对象的对应值中。
newObj[i] = shalHighCopy(obj[i]);
} else {
newObj[i] = obj[i];
}
}
}
return newObj;
}
return obj;
}
let newObj2 = shalHighCopy(obj);
console.log("----------------------------使用for...in方法 递归实现深复制----------------------------");
console.log(newObj2);
newObj2.arr[1] = '0';
newObj2.obj1.key = 'shuyan4';
console.log(obj);
console.log(newObj2);
使用json方法实现
- 方法二:使用json方法实现
function jsonCopy(obj) {
let _temp = JSON.stringify(obj); //将对象转化为字符串形式
let temp = JSON.parse(_temp); //将字符串转化为对象
return temp;
}
let newObj3 = shalHighCopy(obj);
console.log("----------------------------使用json方法实现深复制----------------------------");
console.log(newObj3);
newObj3.arr[2] = '2';
newObj3.obj1.key = 'shuyan5';
console.log(obj);
console.log(newObj3);
Array.prototype.forEach
-
方法三:利用数组的Array.prototype.forEach进copy
let deepClone = function(obj) { let copy = Object.create(Object.getPrototypeOf(obj)); let propNames = Object.getOwnPropertyNames(obj); propNames.forEach(function(items) { let item = Object.getOwnPropertyDescriptor(obj, items); Object.defineProperty(copy, items, item); }); return copy; };