一、数据类型
基本数据类型(String,Number,Boolean,null,Undefined):直接存储在栈(stack)中的数据
引用数据类型(object):存储时会在栈内存存储引用(堆内存中存值的地址),堆内存存储真正的值,栈内存中的引用指向堆内存的值。
二、浅拷贝与深拷贝
浅拷贝:当把一个对象赋值给一个新的变量时,复制的其实是该对象的在栈中的引用地址(指向某个对象的指针),而不是对象值本身,新旧对象指向堆内存中同一片地址空间,共享同一块堆内存,无论哪个对象发生变化,其实都是改变的内存空间的内容,因此,两个对象是联动的
深拷贝:在堆内存中重新开辟一块空间,存放原对象的值,让栈中的引用指向这块新的内存地址,新旧对象不在相互影响
三、实现深拷贝的方式
1. 递归函数调用
const deepClone = (source) => {
if (!source && typeof source !== 'object') {
throw new Error('error arguments', 'deepClone')
}
const targetObj = source.constructor === Array ? [] : {}
Object.keys(source).forEach(keys => {
if (source[keys] && typeof source[keys] === 'object') {
targetObj[keys] = deepClone(source[keys])
} else {
targetObj[keys] = source[keys]
}
})
return targetObj
}
2. JSON.stringify + JSON.parse
const obj = {
name: 'dd',
age: 18,
say: {
text: 'hello'
}
}
const str = JSON.stringify(obj)
let obj2 = JSON.parse(str)
obj2.say.text = 'hi'
console.log(obj); //{ name: 'dd', age: 18, say: { text: 'hello' } }
console.log(obj2); //{ name: 'dd', age: 18, say: { text: 'hi' } }
注意:JSON.string实现深拷贝有几个特点:
const obj3 = {
func: function () { console.log(1) },
obj: { name: 'h' },
arr: [1, 2, 3],
und: undefined,
ref: /^123$/,
date: new Date(),
NaN: NaN,
infinity: Infinity,
sym: Symbol(1)
}
console.log(JSON.parse(JSON.stringify(obj3)))
// NaN: null
// arr: (3) [1, 2, 3]
// date: "2023-02-07T10:27:29.165Z"
// infinity: null
// obj: {name: 'h'}
// ref: {}
拷贝的对象的值如果有函数,undefined,symbol 这几种类型,经过 JSON.stringify 序列化后字符串中这个键值对会消失。
拷贝 Date 类型会变成字符串
无法拷贝不可枚举的属性
无法拷贝对象原型链
拷贝 RegExp 引用类型会变成空对象
对象中含有 NaN、infinity 以及 -infinity,JSON 序列化后的结果变成 null
3. lodash (js库)
const _ = require('lodash')
const foo = {
name: '张三',
info: {
age: 24
}
}
const newFoo = _.cloneDeep(foo);
foo.info.age = 25
console.log(foo, newFoo) // { name: '张三', info: { age: 25 } } { name: '张三', info: { age: 24 } }
4. Object.assign
注意:只有当对象中没有嵌套对象时,才可以实现深拷贝
const foo = {
name: '张三',
age: 24
}
const newFoo = Object.assign({}, foo)
foo.age = 25
console.log(foo, newFoo) // {name: '张三', age: 25} {name: '张三', age: 24}
// 对象中有内嵌的对象时
const foo = {
name: '张三',
info: {
age: 24
}
}
const newFoo = Object.assign({}, foo)
foo.info.age = 25
console.log(foo, newFoo) // { name: '张三', info: { age: 25 } } { name: '张三', info: { age: 25 } }
5.structuredClone
const foo = {
name: '张三',
info: {
age: 24
}
}
const newFoo = structuredClone(foo) //
foo.info.age = 25
console.log(foo, newFoo) // { name: '张三', info: { age: 25 } } { name: '张三', info: { age: 24 } }