前置知识
- js的一般数据类型的存储
- js的引用类型的数据存储
- 基本数据类型
- null
- undefined
- boolean
- string
- number
- symbol
浅拷贝 深拷贝
- 浅拷贝是创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝,如果属性是基本类型,拷贝的就是基本类型的值。如果属性是引用类型题,拷贝的就是内存地址。所以如果其中一个对象改变了这个地址,就会影响到另一个对象。
- 深拷贝是将一个对象从内存中完整的拷贝一份出来,从堆内存中开辟一个新的区域存放新对象,且修改新对象不会影响原对象。
针对引用类型来说,赋值、深拷贝、浅拷贝的区别
- 浅拷贝 赋值的区别
- 当我们把一个对象赋值给一个新的变量时,赋的其实是该对象在栈中的地址,而不是堆中的数据。也就是两个对象指向的是同一个存储空间,无论哪个对象发生改变,其实都是改变的存储空间的内容,因此,两个对象是联动的。
- 浅拷贝:重新在堆中创建内存,拷贝前后对象的基本数据类型不影响,但拷贝前后对象的引用类型因共享同一块内存,会相互影响。
- 深拷贝:从堆内存中开辟一个新的区域存放新对象,对对象中的子对象进行递归拷贝,拷贝前后的两个对象互不影响。
var person = {
name:'爱就一个字',
hobby:['学习',['看电影','购物'],'锻炼'],
date:new RegExp('\\w+'),
function(){}
}
var person1 = person;
person1.name = '王晓星'
person1.hobby[0] = '玩游戏';
console.log(person)
console.log(person1);
function shallowCopy(obj){
var target = {}
for(var i in obj){
if(obj.hasOwnProperty(i)){
target[i] = obj[i]
}
}
return target
}
var person1 = shallowCopy(person)
person1.name = '王晓星'
person1.hobby[0] = '玩游戏';
console.log(person)
console.log(person1);
function deepClone(obj){
var cloneObj = new obj.constructor()
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;
for(var i in obj){
if(obj.hasOwnProperty(i)){
cloneObj[i] = deepClone(obj[i])
}
}
return cloneObj
}
var person1 = JSON.parse(JSON.stringify(person))
person1.name = '王晓星'
person1.hobby[0] = '玩游戏';
console.log(person)
console.log(person1);
浅拷贝的实现方式
Object.assign()
lodash
里面的_.clone
...
展开运算符Array.prototype.concat
Array.prototype.slice
深拷贝的实现方式
JSON.parse(JSON.stringify())
- 递归的操作
cloneDeep
Jquery.extend()
js的拷贝 | 和原数据是否指向同一对象 | 第一层数据为一般数据类型 | 第一层数据不是原始数据 |
---|
赋值 | 是 | 改变会使原始数据一同改变 | 改变会使原始数据一同改变 |
浅拷贝 | 否 | 改变不会使原始数据一同改变 | 改变会使原始数据一同改变 |
深拷贝 | 否 | 改变不会使原始数据一同改变 | 改变不会使原始数据一同改变 |