亦舒的海角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)
複製代碼