/*
最新的ECMAScript标准定义了 8 种数据类型:
6 种原始数据类型:Boolean,undefined,Number,BigInt,String,Symbol
null Object Function
*/
/*
数据分为: 基本数据类型 & 引用数据类型
基本数据类型:String,Number,Boolean,null,undefined,Symbol.(基本数据类型都是直接存储在栈中的数据)
引用数据类型:Array,Object.(引用数据类型存储的是该对象在栈中引用,真实的数据存储在内存中)
*/
// 基本数据类型
/* let str1 = '123'
let str2 = str1
str2 = '456'
console.log(str1) //123
console.log(str2) //456 */
// 引用数据类型
/* let arr1 = [1, 2, 3]
let arr2 = arr1
arr2.push(4)
console.log(arr1) // [1, 2, 3, 4]
console.log(arr2) // [1, 2, 3, 4] */
/*
如上,由于基本数据类型是直接存储的,所以如果我们对基本数据类型进行拷贝,然后修改新数据后,不会影响到原数据。
而当你对引用数据类型进行拷贝,然后修改新数据后,它就会影响到原数据
*/
/*
赋值:引用地址的拷贝。修改赋值后的数据,不管是基本数据类型还是引用数据类型,都会影响到原数据。
浅拷贝:一层拷贝。在浅拷贝中,修改基本数据类型不会影响原有数据的基本数据类型,修改引用数据类型会影响原有的数据类型。
深拷贝:无限层级拷贝。在深拷贝中,修改基本数据类型和引用数据类型都不会影响原有的数据类型。
*/
// 手写浅拷贝
/* const arr1 = [2,1,1,['rose','lisa'],327]
const shallowClone = (arr) => {
const pcy = []
for (let p in arr) {
if (arr.hasOwnProperty(p)) {
pcy[p] = arr[p]
}
}
return pcy
}
const arr2 = shallowClone(arr1)
arr2[3].push('彩松鼠')
arr2[4] = 521
console.log(arr1,'原始数据')
console.log(arr2,'浅拷贝并修改') */
/*
修改引用数据类型的时候会影响到原数据,修改基本类型不会影响原数据
for...in:遍历 Object 对象 arr1,将可枚举值列举出来。
hasOwnProperty():检查该枚举值是否属于该对象 arr1,如果是继承过来的就去掉,如果是自身的则进行拷贝。
*/
// 实现快速浅拷贝
/*
Object.assign() 方法可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。
但是需要注意的是,Object.assgin() 进行的是浅拷贝,拷贝的是对象的属性的引用,而不是对象本身。
Object.assign() 对于第一层的数据来说,是深拷贝,对于第二层及以上的数据来说,是浅拷贝。
*/
/* const obj1 = {
username: '211',
skill: {
music: ['make you mine', 'ghosts'],
read: 'book'
},
idol: ['rose', 'lisa', 'jisoo', 'jennie']
}
const obj2 = Object.assign({}, obj1)
obj2.username = '贰壹壹' //修改基本类型
obj2.skill.music.push('18') //修改二层引用类型
obj2.skill.read = 'novel book' //修改二层基本类型
obj2.idol = ['BLACKPINK'] //修改引用类型
console.log(obj1, '原数据')
console.log(obj2, '浅拷贝并修改') */
/*
concat() 是数组的一个内置方法,用户合并两个或者多个数组。这个方法不会改变现有数组,而是返回一个新数组。
修改基本类型不影响原数据,修改引用类型会影响原数据
*/
/* const arr1 = [211,{idol: 'BLAKCPINK'}]
const arr2 = arr1.concat()
arr2[0] = 327
arr2[1].idol = '朴彩英'
console.log(arr1, '原数据')
console.log(arr2, '浅拷贝并修改') */
/*
slice() 也是数组的一个内置方法,该方法会返回一个新的对象。不会改变原数组
和concat()浅拷贝一模一样
*/
/* const arr1 = [211,{idol: 'BLAKCPINK'}]
const arr2 = arr1.slice()
arr2[0] = 327
arr2[1].idol = '朴彩英'
console.log(arr1, '原数据')
console.log(arr2, '浅拷贝并修改') */
/*
... 展开运算符
是 ES6 中新提出来的一种运算符。
在拷贝数组、对象以及拼接数组等方面都可以使用。
*/
/* // 浅拷贝数组
const arr1 = [211,{idol: 'BLAKCPINK'}]
const arr2 = [...arr1]
arr2[0] = 327
arr2[1].idol = '朴彩英'
console.log(arr1, '原数据')
console.log(arr2, '浅拷贝并修改')
// 浅拷贝对象
const obj1 = {
username: '211',
skill: {
music: ['make you mine', 'ghosts'],
read: 'book'
},
idol: ['rose', 'lisa', 'jisoo', 'jennie']
}
const obj2 = {...obj1}
obj2.username = '贰壹壹' //修改基本类型
obj2.skill.music.push('18') //修改二层引用类型
obj2.skill.read = 'novel book' //修改二层基本类型
obj2.idol = ['BLACKPINK'] //修改引用类型
console.log(obj1, '原数据')
console.log(obj2, '浅拷贝并修改') */
// 深拷贝
/*
JSON.parse(JSON.stringify())。
JSON.stringify():将对象转成 JSON 字符串。
JSON.parse():将字符串解析成对象。
通过 JSON.parse(JSON.stringify()) 将 JavaScript 对象转序列化(转换成 JSON 字符串),再将其还原成 JavaScript 对象,一去一来我们就产生了一个新的对象,而且对象会开辟新的栈,从而实现深拷贝。
注意,该方法的局限性:
1、不能存放函数或者 Undefined,否则会丢失函数或者 Undefined;
2、不要存放时间对象,否则会变成字符串形式;
3、不能存放 RegExp、Error 对象,否则会变成空对象;
4、不能存放 NaN、Infinity、-Infinity,否则会变成 null;
5、……更多请自行填坑,具体来说就是 JavaScript 和 JSON 存在差异,两者不兼容的就会出问题。
*/
/* const arr1 = [211,{idol: 'BLAKCPINK'}]
const arr2 = JSON.parse(JSON.stringify(arr1))
arr2[0] = 327
arr2[1].idol = '朴彩英'
console.log(arr1, '原数据')
console.log(arr2, '深拷贝并修改') */
浅拷贝和深拷贝
最新推荐文章于 2024-06-27 01:38:03 发布