一、数据类型
数据分为基本数据类型(String, Number, Boolean, Null, Undefined,Symbol)和对象数据类型。
- 基本数据类型的特点:直接存储在栈(stack)中的数据
- 引用数据类型的特点:存储的是该对象在栈中引用,真实的数据存放在堆内存里
引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4SgOtckC-1689157153527)(D:\内部技术文档\mysql相关\img\031.png)]
二、浅拷贝和深拷贝对原始数据的影响
– | 和原始数据是否指向同一对象 | 第一层数据为基本数据类型 | 原数据中包含子对象 |
---|---|---|---|
赋值 | 是 | 改变会使原数据一同改变 | 改变会使原数据一同改变 |
浅拷贝 | 否 | 改变不会使原数据一同改变 | 改变会使原数据一同改变 |
深拷贝 | 否 | 改变不会使原数据一同改变 | 改变不会使原数据一同改变 |
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Xnuck3Uu-1689157153528)(D:\内部技术文档\mysql相关\img\032.png)]
三、使用 Object.assign()
的注意点
Object.assign()
方法可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。但是 Object.assign()
进行的是浅拷贝,拷贝的是对象的属性的引用,而不是对象本身。
let a = {
name: 'Iceman',
book: { price: '45'}
}
let b = Object.assign({}, a)
console.log(b)
// {
// name: 'Iceman',
// book: { price: '45'}
// }
a.name = 'change'
a.book.price = '55'
console.log(a)
// {
// name: 'change',
// book: { price: '55'}
// }
console.log(b);
// {
// name: 'Iceman',
// book: { price: '55'}
// }
四、展开语法 Spread
let a = {
name: 'Iceman',
book: { price: '45'}
}
let b = {...a}
console.log(b)
// {
// name: 'Iceman',
// book: { price: '45'}
// }
a.name = 'change'
a.book.price = '55'
console.log(a)
// {
// name: 'change',
// book: { price: '55'}
// }
console.log(b);
// {
// name: 'Iceman',
// book: { price: '55'}
// }
通过代码可以看出实际效果和 Object.assign()
是一样的。
五、Array.prototype.slice()、Array.prototype.concat()
slice()
方法返回一个新的数组对象,这一对象是一个由 begin
和 end
(不包括 end
)决定的原数组的浅拷贝。原始数组不会被改变。
let a = [0, '1', [2, 3]]
let b = a.slice(1)
console.log(b)
// ['1', [2, 3]]
a[1] = '99'
a[2][0] = 4
console.log(a)
// [0, '99', [4, 3]]
console.log(b)
// ['1', [4, 3]]
可以看出,改变 a[1]
之后 b[0]
的值并没有发生变化,但改变 a[2][0]
之后,相应的 b[1][0]
的值也发生变化。说明 slice()
方法是浅拷贝,相应的还有concat()
等,在工作中面对复杂数组结构要额外注意。
let a = ['1', [2, 3]]
let b = a.concat()
console.log(b)
// ['1', [2, 3]]
a[0] = '99'
a[1][0] = 4
console.log(a)
// ['99', [4, 3]]
console.log(b)
// ['1', [4, 3]]
结果concat()
与slice()
一样。
六、关于JSON.parse(JSON.stringify())
实现深拷贝
let a = {
name: 'Iceman',
book: { price: "45"}
}
let b = JSON.parse(JSON.stringify(a))
console.log(b)
// {
// name: 'Iceman',
// book: { price: "45"}
// }
a.name = 'change'
a.book.price = '55'
console.log(a)
// {
// name: 'change',
// book: { price: '55'}
// }
console.log(b)
// {
// name: 'Iceman',
// book: { price: '45'}
// }
该方法有以下几个问题:
- 会忽略
undefined
- 会忽略
symbol
- 不能序列化函数
- 不能解决循环引用的对象
let obj = {
name: 'Iceman',
a: undefined,
b: Symbol('Iceman'),
c: function() {}
}
console.log(obj)
// {
// name: "Iceman",
// a: undefined,
// b: Symbol(Iceman),
// c: ƒ ()
// }
let b = JSON.parse(JSON.stringify(obj))
console.log(b)
// {name: 'Iceman'}
let obj = {
a: 1,
b: {
c: 2,
d: 3
}
}
obj.a = obj.b
obj.b.c = obj.a
let b = JSON.parse(JSON.stringify(obj))
// Uncaught TypeError: Converting circular structure to JSON