亦舒的海角json
又回到这个老生常谈,新生绝望的问题,一般遇到这种你们都比较熟悉的问题,反而不知道怎么列大纲,怕不够深刻也怕脱离主题~segmentfault
emm..数组
此文系 不要再问我XX系列之 不要再问我JS Clone的问题了bash
clone
原本很简单,只是由于JS中不一样的数据类型存储方式(堆和栈)的差别,咱们才会以为它貌似有点‘复杂’数据结构
基本类型和引用类型的差别如上图所示了 它们共同的目标就是以一个对象为原型clone出另一个新对象,由于自身的问题产生一些反作用,三者的差别其实就体如今反作用的差别上post
基础类型: 值存放在栈中,比较是值的比较 引用类型: 值存放在堆中,变量其实是一个存放在栈内存的指针,这个指针指向堆内存中的地址。每一个空间大小不同,要根据状况开进行特定的分配,引用类型的比较是引用的比较ui
var person1 = [1,2,3];
var person2 = [1,2,3];
console.log(a === b); // false
复制代码
赋值的概念 即便刚入行也不陌生,天天都在用的'='
spa
var obj1 = {
name:'maying',
age:22,
sex:'女',
language : [1,[2,3],[4,5],[9,0]]
}
var sringD = 'pre';
var obj3 = sringD;
sringD = 'post';
var obj2 = obj1;
obj1.name = 'gaile',
obj1.language[0] = 'jjj'
console.log('obj1',obj1)
/*
{
age: 22
language: (4) ["jjj", Array(2), Array(2), Array(2)]
name: "gaile"
sex: "女"
}
*/
console.log('obj2',obj2)
/*
age: 22
language: (4) ["jjj", Array(2), Array(2), Array(2)]
name: "gaile"
sex: "女"
*/
console.log('sringD',sringD) //post
console.log('obj3',obj3) //pre
复制代码
以前的不少年,我认为赋值差很少等于浅拷贝 写个小demo 发现它们之间的差别指针
var obj2 = obj1;
var obj3 = {...obj1};
obj1.name = 'gaile',
obj1.language[0] = 'jjj'
console.log('obj1',obj1)
console.log('obj2',obj2)
console.log('obj3',obj3)
复制代码
obj1.name
的时候不会影响到它,可是改变引用类型时就不能幸免了
所谓的浅拷贝就是:code
language : [1,[2,3],[4,5],[9,0]]
复制代码
内部的子对象的指针仍是同一个地址
若是要实现一直往下复制 就引出了接下来要说的深拷贝
结论:浅复制要比复制来的深入一点,至少它开辟了一个新对象,一起新的堆内存
站在巨人的肩膀上,咱们能够轻松实现浅拷贝
1. b = [...a]
2. b = a.slice(0) / [].slice.call(a,0)
3. b = a.concat() / [].concat.call(a)
复制代码
1. b = Object.assign({},a)
2. b = {...a}
复制代码
原理:遍历对象的每一个属性进行逐个拷贝
function copy(obj) {
if (!obj || typeof obj !== 'object') {
return
}
var newObj = obj.constructor === Array ? [] : {}
for (var key in obj) {
if(obj.hasOwnProperty(key)){
newObj[key] = obj[key]
}
}
return newObj
}
复制代码
深拷贝的意义,就是彻底复制,若是你读了上文,应该就没有什么疑问了
将a对象复制一份给对象b,无论a中的数据结构嵌套有多深,当改变a对象中的任意深度的某个值后,b中的该值不会受任何影响
JSON.stringify()``和JSON.parse()
的混合配对使用var obj4 = JSON.parse(JSON.stringify(obj1))
obj1.name='yishu',
obj1.language[1] = ["二","三"];
obj4.language[2] = ["四","五"];
console.log(obj1);
console.log(obj4);
复制代码
obj1
,obj4
是两个独立的对象,更改数据互不影响,达到了咱们要的目的
它粗暴,有用,可是也有缺点
在JSON.stringify()
作序列化时,undefined
、function
以及symbol
值,会被忽略例如
var obj = {
a: {b: 'old'},
c:undefined,
d: function () {},
e: Symbol('')
}
var newObj = JSON.parse(JSON.stringify(obj))
newObj.a.b = 'new'
console.log(obj)
console.log(newObj)
复制代码
结果
原理:使用递归,遍历每个对象属性进行拷贝
var obj = {
a: {b: 'old'},
c:undefined,
d: function () {},
e: Symbol('')
}
function copy(obj) {
if (!obj || typeof obj !== 'object') {
return
}
var newObj = obj.constructor === Array ? [] : {}
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
if (typeof obj[key] === 'object' && obj[key]) {
newObj[key] = copy(obj[key])
} else {
newObj[key] = obj[key]
}
}
}
return newObj
}
var newObj = copy(obj)
newObj.a.b = 'new'
console.log(obj)
console.log(newObj)
复制代码