JavaScript中存在两大数据类型:
- 基本类型
- Number类型
- String类型
- Boolean类型
- Null类型
- Undefined类型
- Biglnt类型
- 字符串类型
- 符号类型
- 引用类型
- Object 类型
- Array 类型
- Date 类型
- RegExp 类型
- Function 类型
基本类型:保存在在栈内存中,它们的值直接存储在变量访问的位置,在将一个保存着原始值的变量复制给另一个变量时,会将原始值的副本赋值给新变量,此后这两个变量是完全独立的,它们只是拥有相同的 value 而已,a 不全等 b。
引用类型:保存在堆内存中,引用数据类型的变量是一个指向堆内存中实际对象的引用,存在栈中,在将一个保存着对象内存地址的变量复制给另一个变量时,会把这个内存地址赋值给新变量,也就是说这两个变量都指向了堆内存中的同一个对象,它们中任何一个作出的改变都会影响另一个,a 全等 b,因为它们的指针指向同一个堆内存。
原数据
let a = {
name: '张三',
age: 19,
list: [1, 2, 3]
},
arr = [4,5,6];
赋值
- 对象数组赋值给一个新的变量时,其实是赋的内存地址,而不是对象中的数据。所以修改一个将影响另外一个。
let b= a;
a.age = 20;
a.list = arr;
a.list[0] = '3';
console.log(a); // {name: "张三", age: 20, list:["3", 5, 6]}
console.log(b); // {name: "张三", age: 20, list:["3", 5, 6]}
console.log(arr); // ["3", 5, 6]
浅拷贝
- 浅拷贝是创建新的数据,重新在堆中创建内存,拷贝的是基本类型则互不影响,但是拷贝的引用类型共享同一个内存地址,会互相影响。
const deepClone=(obj)=> {
const newObj = {};
for(let prop in obj) {
if(obj.hasOwnProperty(prop)){
newObj[prop] = obj[prop];
}
}
return newObj;
}
let b= deepClone(a);
console.log(b); // {name: "张三", age: 19, list: [1, 2, 3]}
b.age = 20;
b.list[0] = '3';
console.log(a); // {name: "张三", age: 19, list:["3", 2, 3]}
console.log(b); // {name: "张三", age: 20, list:["3", 2, 3]}
深拷贝
- 深拷贝是从堆内存中从新创建一个区域来存放新对象,两个对象属完成相同,但是对应两个不同的地址,修改一个对象的属性,互不影响。
常见的深拷贝方式
- _.cloneDeep()
- JSON.stringify()
- 手写循环递归
- jQuery.extend()
_.cloneDeep()
const _ = require('lodash');
let b= _.cloneDeep(a);
console.log(a.list===b.list); // false
JSON.stringify()
let a = {
c: 'c',
c1: undefined,
c2: function() {},
c3: Symbol('c')
}
let b= JSON.parse(JSON.stringify(a));
// 存在弊端 会忽略undefined、symbol和函数
console.log(b); // {c: "c"}
手写循环递归
const deepClone=(obj, hash = new WeakMap()) =>{
// 如果为null或者undefined则不进行拷贝操作
if (obj === null) return obj;
if (obj instanceof Date) return new Date(obj);
if (obj instanceof RegExp) return new RegExp(obj);
// 可能是对象或者普通的值 如果是函数的话是不需要深拷贝
if (typeof obj !== "object") return obj;
// 是对象的话就要进行深拷贝
if (hash.get(obj)) return hash.get(obj);
let cloneObj = new obj.constructor();
// 找到的是所属类原型上的constructor,而原型上的 constructor指向的是当前类本身
hash.set(obj, cloneObj);
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
// 实现一个递归拷贝
cloneObj[key] = deepClone(obj[key], hash);
}
}
return cloneObj;
}
//调用函数
deepClone(a)
jQuery.extend()
const $ = require('jquery');
let b= $.extend(true, {}, a);
console.log(a.list===b.list); // false