基本数据类型存放在栈内存中,引用数据类型如对象、数组存放在堆内存中,其变量是存在栈内存中的指针。
比较两个引用类型变量时,是比较的地址,而不是比较的引用类型的值。
var a = [1,2,3];
var b = [1,2,3];
console.log(a === b); // false
浅拷贝:
直接复制、Object.assign()、concat、slice、展开运算符(只拷贝一层)
for…in…
var obj={
id:1,
name:'andy',
msg:{
age:18
}
}
var o={};
for(var k in obj){
o[k]=obj[k];//只拷贝地址
}
//console.log(obj);
//o.msg.age=20;
//console.log(obj);
ES6中实现浅拷贝Object.assign(target,…sources)
var obj={
id:1,
name:'andy',
msg:{
age:18
}
}
var o={};
Object.assign(o,obj);
console.log(o);
手写Object.assign,即浅拷贝:
Object.myAssign = function(target, ...source) {
if (target == null) {
throw new TypeError('Cannot convert undefined or null to object')
}
let ret = Object(target)
source.forEach(function(obj) {
if (obj != null) {
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
ret[key] = obj[key]
}
}
}
})
return ret
}
concat
var a = [1, [2, 3, 4], {
name: 'Fan'
}];
var b = a.concat(5)//b=[1,[2,3,4],{name:'fan'},5]
a[0] = 6;
console.log(b[0]) // 1 看起来像深拷贝
a[1][0] = 999;
console.log(b[1][0]) // 999 浅拷贝
a[2].name = 'Liu'
console.log(b[2].name) // 'Liu' 浅拷贝
slice
var a = [1, [2, 3, 4], {
name: 'Fan'
}];
var b = a.slice(0)
a[0] = 6;
console.log(b[0]) // 1 看起来像深拷贝
a[1][0] = 999;
console.log(b[1][0]) // 999 浅拷贝
a[2].name = 'Liu'
console.log(b[2].name) // 'Liu' 浅拷贝
展开运算符…
只拷贝一层
var person1 = {
name: '小明',
age: 18,
sex: '男',
hobby: {
music: '伤感类歌曲',
like: '吃饭、睡觉、打游戏',
}
}
var xiaoHong = {...person1}
xiaoHong.name = '小红';
xiaoHong.hobby.music = '小清新歌曲';
console.log(person1)
// 输出: {name: "小明", age: 18, sex: "男", hobby: {music: "小清新歌曲",like: "吃饭、睡觉、打游戏"}}
console.log(xiaoHong)
// 输出: {name: "小红", age: 18, sex: "男", hobby: {music: "小清新歌曲",like: "吃饭、睡觉、打游戏"}}
深拷贝:
JSON.parse(JSON.stringify())
var str1 = {
name: 'Fan',
age: 22,
other: {
school: 'HuangHuai'
}
}
var str2 = JSON.parse(JSON.stringify(str1));//JSON.stringify将对象转变为字符串,这样用JSON.parse时是在为一个字符串转对象开辟新的内存空间
str2.name = 'Jun'
console.log(str1.name) // Fan
str2.other.school = 'ShiYan'
console.log(str1.other.school) // HuangHuai
缺点:只能拷贝符合JSON格式的数据,不能拷贝函数。
开辟新内存+递归
function deepClone(source){
if(source===null) return source;
if(source instanceof Date) return new Date(source);
if(source instanceof RegExp) return new RegExp(source);
const target=Array.isArray(source)?[]:{};
for(let key in source){//for...in...遍历会遍历到原型链上的属性
if(source.hasOwnProperty(key)){//只复制元素自身的属性,不复制原型链上的
target[key]= (typeof source[key]==='object'?deepClone(source[key]):source[key]);
}
}
return target;
}