賦值
- 基本型別: 傳值,在堆疊記憶體中的資料發生資料變化的時候,系統會自動為新的變數分配一個新的之值在堆疊記憶體中,兩個變數相互獨立,互不影響的
- 參考型別: 傳址,只改變指標的指向,指向同一個物件,兩個變數相互干擾
//基本資料型別賦值
var a = 10;
var b = a;
a++ ;
console.log(a); // 11
console.log(b); // 10
//參考資料型別賦值
let a = { name: '11' }
let b = a
b.name = '22'
console.log(a.name) // 22
console.log(b.name) // 22
淺拷貝
- 對于基本型別,淺拷貝是對值的復制,拷貝前后物件的基本資料型別互不影響
- 對于參考型別來說,淺拷貝是對物件地址的復制, 也就是拷貝的結果是兩個物件指向同一個地址,所以如果其中一個物件改變了這個地址,就會影響到另一個物件
注意:淺拷貝只復制一層物件的屬性
實作淺拷貝方法
方法一:Object.assign
**語法:Object.assign(target, ...sources) **
ES6中拷貝物件的方法,接受的第一個引數target是拷貝后的物件,剩下的引數是要拷貝的物件sources(可以是多個)
例1:
let target = {};
let source = {a:'11',b:{name:'duoduo'}};
Object.assign(target ,source);
console.log(target); // { a: '11', b: { name: 'duoduo' } }
例2:
let target = {};
let source = {a:'11',b:{name:'duoduo'}};
Object.assign(target ,source);
source.a = '22';
source.b.name = 'nana'
console.log(source); // { a: '22', b: { name: 'nana' } }
console.log(target); // { a: '11', b: { name: 'nana' } }
Object.assign注意事項
- 只拷貝源物件的自身屬性(不拷貝繼承屬性)
- 它不會拷貝物件不可列舉的屬性
undefined和null無法轉成物件,它們不能作為Object.assign引數,但是可以作為源物件- 屬性名為
Symbol值的屬性,可以被Object.assign拷貝,
方法二:Array.prototype.slice
實作原陣列的淺拷貝
var a = [ 1, 3, 5, { x: 1 } ];
var b = Array.prototype.slice.call(a);
b[0] = 2;
console.log(a); // [ 1, 3, 5, { x: 1 } ];
console.log(b); // [ 2, 3, 5, { x: 1 } ];
// 從輸出結果可以看出,淺拷貝后,陣列a[0]并不會隨著b[0]改變而改變
// 說明a和b在堆疊記憶體中參考地址并不相同,
var a = [ 1, 3, 5, { x: 1 } ];
var b = Array.prototype.slice.call(a);
b[3].x = 2;
console.log(a); // [ 1, 3, 5, { x: 2 } ];
console.log(b); // [ 1, 3, 5, { x: 2 } ];
// 從輸出結果可以看出,淺拷貝后,陣列中物件的屬性會根據修改而改變
// 說明淺拷貝的時候拷貝的已存在物件的物件的屬性參考,
方法三:Array.prototype.concat
let array = [{a: 1}, {b: 2}];
let array1 = [{c: 3},{d: 4}];
let array2=array.concat(array1);
array1[0].c=123;
console.log(array2);// [ { a: 1 }, { b: 2 }, { c: 123 }, { d: 4 } ]
console.log(array1);// [ { c: 123 }, { d: 4 } ]
方法四:...擴展運算子
語法:var cloneObj = { ...obj };
var a = [ 1, 3, 5, { x: 1 } ];
var b = {...a};
b[0] = 2;
console.log(a); // [ 1, 3, 5, { x: 1 } ];
console.log(b); // [ 2, 3, 5, { x: 1 } ];
// 從輸出結果可以看出,淺拷貝后,陣列a[0]并不會隨著b[0]改變而改變
// 說明a和b在堆疊記憶體中參考地址并不相同,
var a = [ 1, 3, 5, { x: 1 } ];
var b = {...a};
b[3].x = 2;
console.log(a); // [ 1, 3, 5, { x: 2 } ];
console.log(b); // [ 1, 3, 5, { x: 2 } ];
// 從輸出結果可以看出,淺拷貝后,陣列中物件的屬性會根據修改而改變
// 說明淺拷貝的時候拷貝的已存在物件的物件的屬性參考,
其他方法:
//淺拷貝實作
var obj = { a:1, arr: [2,3] };
var shallowObj = shallowCopy(obj);
function shallowCopy(src) {
var dst = {};
for (var prop in src) {
if (src.hasOwnProperty(prop)) {
dst[prop] = src[prop];
}
}
return dst;
}
shallowObj.arr[1] = 5;
obj.arr[1] // = 5
深拷貝
深拷貝開辟一個新的堆疊,兩個物件對應兩個不同的地址,修改一個物件的屬性,不會改變另一個物件的屬性
注意:深拷貝對物件中的子物件進行遞回拷貝,拷貝前后兩個物件互不影響
實作方法:
方法一:JSON.parse(JSON.stringify())
- JSON.stringify()是前端開發程序中比較常用的深拷貝方式,
- 原理是把一個物件序列化成為一個JSON字串,將物件的內容轉換成字串的形式再保存在磁盤上,再用JSON.parse()反序列化將JSON字串變成一個新的物件
let arr = [1, 2, {name: ' duoduo'}];
let newarr = JSON.parse(JSON.stringify(arr));
newarr[2].name = 'nana';
console.log(newarr); // [ 1, 2, { username: 'nana' } ]
console.log(arr); // [ 1, 2, { username: 'duoduo' } ]
JSON.stringify()實作深拷貝注意點
- 拷貝的物件的值中如果有函式,undefined,symbol則經過JSON.stringify()序列化后的JSON字串中這個鍵值對會消失
- 無法拷貝不可列舉的屬性,無法拷貝物件的原型鏈
- 拷貝Date參考型別會變成字串
- 拷貝RegExp參考型別會變成空物件
- 物件中含有NaN、Infinity和-Infinity,則序列化的結果會變成null
- 無法拷貝物件的回圈應用(即obj[key] = obj)
方法二:jquery 的 $.extend
var $ = require('jquery');
var obj1 = {
a: 1,
b: { f: { g: 1 } },
c: [1, 2, 3]
};
var obj2 = $.extend(true, {}, obj1);
賦值、深拷貝、淺拷貝
淺拷貝和深拷貝****區別
淺拷貝只復制一層物件的屬性,而深拷貝則遞回復制了所有層級
**
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/109908.html
標籤:JavaScript
上一篇:獲取頁面元素的位置
下一篇:前端程式員的進階
