標題對象的深淺拷貝
在進行實例講解之前,我們先下個給深淺拷貝下個定義,什麼是深拷貝?什麼是淺拷貝?
個人理解:
- 淺拷貝:針對指針的引用
- 深拷貝: 對值的引用
淺拷貝
先看🌰:
var obj = {
a: 1,
b: 2,
};
var newObj = obj
obj.a = 3
console.log(obj.a) // 3
console.log(newObj.a) // 3
深拷貝
var obj = {
a: 1,
b: 2,
};
var newObj = {};
Object.keys(obj).map(item => {
newObj[item] = obj[item];
});
obj.a = 666
console.log(obj.a) // 666
console.log(newObj.a) // 1
比較🌰1 和 例子2 的不同,這裏將 1 (針對地址的引用) 稱之爲淺拷貝,2 (針對屬性的拷貝) 稱之爲深拷貝,
區別也是顯而易見的
案列:實現對象深拷貝的
var obj = {
a: 1,
b: 2,
c: { sex: "man", options: { age: 22 } }
};
var newObj = {};
function objDeep(newObj, obj) {
Object.keys(obj).map(item => {
if (obj[item] && !(obj[item] instanceof Object)) {
newObj[item] = obj[item];
} else {
newObj[item] = {};
arguments.callee(newObj[item], obj[item]);
}
});
}
objDeep(newObj, obj);
newObj.a = 999
console.log(obj.a) // 1
console.log(newObj.a) // 999
Object.assign()
既然提到對象的淺拷貝,就不得不提到 Object.assign()
MDN中的解釋爲:Object.assign() 方法用於將 所有可枚舉屬性的值 從一個或多個源對象複製到目標對象。它將返回目標對象。
舉例:
Object.assign(target, source)
var obj = { a: 1, b: 2 };
var copy = Object.assign({a: 3}, obj);
console.log(copy); // { a: 1, b: 2 }
這裏注意:源對象中的屬性會代替目標對象的同名屬性,這也就導致目標對象中的 {a: 3} 最終被替換爲 {a: 1} 的結果
既然談到了是可枚舉屬性,那我們再來看看不可枚舉屬性
對象的 數據屬性 和 訪問器屬性 請自行查看 高層三, pdf 下載地址
// 通過 Object.create() 創建的對象,默認都是不可枚舉的,需要手動設置
var obj = Object.create({foo: 1}, { // foo 是個繼承屬性。
a: {
name: 'lilie' // a 是個不可枚舉屬性。
},
b: {
name: 'lili',
enumerable: true // b 是個自身可枚舉屬性。
}
});
var copy = Object.assign({}, obj);
console.log(copy); // { b: 'lili' }
爲啥Object.assign() 是淺拷貝,我們再來看一個🌰:
var obj = { a: 1, b: [1,3],c: {name: 'name', age: 30} };
var copy = Object.assign({a: 3}, obj);
obj.a = 999
console.log(obj.a) // 999
console.log(copy.a); // 1
寫到這裏,根據控制檯打印結果,我反問自己,這不就是深拷貝麼,事實上,你可以簡單粗暴的這麼理解,因爲MDN解釋很清楚了, Object.assign() 是對值的引用
- 到次爲此,我們已經知道了兩種關於對象深拷貝的方法
我們不妨再來一個騷操作:
var obj = { a: 1, b: [1,3],c: {name: 'name', age: 30} };
var copy = JSON.parse(JSON.stringify(obj)) // 先轉化爲字符串,在轉化爲json對象,相當於完完全全拷貝了一個副本
obj.a = 999
console.log(obj.a) // 999
console.log(copy.a); // 1
到這裏,應該基本上差不多了
但是筆者我不忍心,Object.assign() 感覺很像對象的去重複,各位看官有木有,既然如此,我們順便把 數組的去重 和 扁平化處理 的面試常遇到的代碼順便分享一下
一下關於 es6 的相關知識,如果不太瞭解,請移步至 es6 教程
數組的去重
let arr = [1, 5, 46, 79, 46, 78, 941, 1111, 1, 1, 1, 1, 1, 1, 1]
let arr0 = [...new Set(arr)] // 通過 es6 的 set 結合 數組的擴展語法
console.log(arr0)
let arr1 = Array.from(new Set(arr)) // 通過 es6 的 set 結合 數組的Array.from
console.log(arr1)
[1,3,4,5,1,2,3,3,4,8,90,3,0,5,4,0].filter(function(elem,index,Array){
return index === Array.indexOf(elem);
})
console.log(r)
let arr2 = [] // 土鱉的循環
for (let i = 0; i < arr.length; i++) {
if (arr2.indexOf(arr[i]) === -1) arr2.push(arr[i])
}
console.log(arr2)
//自定義添加方法去重複方法 可以是各種類型
var arr3= [0, 1, '1', true, 5, true, false, undefined, undefined, null, null];
if (!Array.prototype.unique) {
Array.prototype.unique = function () {
var hash = {}, result = [], type = '', item;
for (var i = 0; i < this.length; i++) {
item = this[i];
type = Object.prototype.toString.call(item);// 專門用來判斷字符串的類型的
if ( !hash[item + type] ) {
hash[item + type] = true;
result.push(item);
}
}
return result;
};
}
console.log(arr3.unique());
//對象的方法來找出先次數最多的數字
var adv={
init:function(){
var arr=[1,2,5,2,5,5,4,1,1,1,2,2,2];
function findNum(arr){
for(var i=0,hash=[];i<arr.length;i++){
hash[arr[i]]=0;
for(var r=0;r<arr.length;r++){
if(arr[i]==arr[r]){
hash[arr[i]]++;
}
}
}
get(hash);
//[4, 5, 1, 3]
// 1 2 4 5
}
function get(hash){
var arr=[];
for(var key in hash){
arr.push(hash[key]);
}
arr.sort(function(a,b){return b-a});
for(var key in hash){
if(hash[key]==arr[0])
console.log(key);
}
}
findNum(arr);
}
}
扁平化處理
/** 數組相關的常用方法 */
const aboutArrayFun = {
/** 扁平化處理 */
// 遞歸
flattenOne: arr => {
var res = [];
for (var i = 0; i < arr.length; i++) {
if (Array.isArray(arr[i])) {
res = res.concat(flattenOne(arr[i]));
} else {
res.push(arr[i]);
}
}
return res;
},
// reduce
flattenTwo: arr => {
return arr.reduce(function(prev, item) {
return prev.concat(Array.isArray(item) ? flattenTwo(item) : item);
}, []);
},
// 擴展運算符
flattenThree: arr => {
while (arr.some(item => Array.isArray(item))) {
arr = [].concat(...arr);
}
return arr;
},
}
關於對象的深淺拷貝就到這裏,以上是個人的理解,其實並不難,只要抓住了重點
更多的乾貨請點擊這裏
react-native 實戰項目學習
歡迎各位看官的批評和指正,共同學習和成長
希望該文章對您有幫助,也希望得到您的鼓勵和支持