直接上程式碼是我的風格
一,賦值
- 基本資料型別的賦值
var a = 10;
var b = a;
b = 24;
console.log(a); // 10 a不受b的影響。
console.log(b) // 24
// 基本資料型別賦值時。。是copy一份10的值。
// 當b=24時。a不受b的影響。
複製程式碼
- 複雜資料型別的賦值
var obj = {
age: 12
}
var obj1 = obj;
obj1.age = 18;
console.log(obj); // {age: 18}
console.log(obj1); // {age: 18}
// 複雜資料型別賦值時。。是copy一份引用地址如0x1111。
// 當obj1 = obj;時。obj和obj1引用一樣。指向同一片堆記憶體空間。
// 所以當obj1.age = 18時。同樣也會更改obj2。
複製程式碼
二,淺拷貝與深拷貝
注意: 淺拷貝和深拷貝都主要針對複雜資料型別
- 淺拷貝:淺拷貝只複製指向某個物件的指標,而不復制物件本身,新舊物件還是共享同一塊記憶體。
- 深拷貝:但深拷貝會另外創造一個一模一樣的物件,新物件跟原物件不共享記憶體,修改新物件不會改到原物件。
二,淺拷貝與賦值
- 淺拷貝
// 直接上程式碼吧
function shallowCopy(oldObj) {
var newObj = {};
for(var prop in oldObj) {
// 所有繼承了 Object 的物件都會繼承到 hasOwnProperty 方法。
// 這個方法可以用來檢測一個物件是否含有特定的自身屬性;如果有返回true。否則返回false
// 和 in 運算子不同,該方法會忽略掉那些從原型鏈上繼承到的屬性。
if(oldObj.hasOwnProperty(prop)){
newObj[prop] = oldObj[prop]
}
}
return newObj;
}
// 淺拷貝
var obj1 = {
a: 1,
b: [2,3,4],
c: [[5,6]] // 注意:這裡多一層引用資料型別
}
var obj2 = shallowCopy(obj1);
obj2.a = 18;
obj2.b = ['二', '三', '四'];
obj2.c[0] = ['五', '六'];
console.log('obj1===',obj1)
console.log('obj2===',obj2)
// 如果物件只有一層。。深拷貝 和 淺拷貝一樣。
複製程式碼
- 賦值
// 賦值
var obj1 = {
a: 1,
b: [2,3,4],
c: [[5,6]] // 注意:這裡多一層引用資料型別
}
var obj3 = obj1;
obj3.a = 18;
obj3.b = ['二', '三', '四'];
obj3.c[0] = ['五', '六'];
console.log('obj1===',obj1)
console.log('obj3===',obj3)
// 共享一片記憶體。所有值都會改變。
複製程式碼
三,淺拷貝實現方式
- 自己封裝
function shallowCopy(oldObj) {
var newObj = {};
for(var prop in oldObj) {
// 所有繼承了 Object 的物件都會繼承到 hasOwnProperty 方法。
// 這個方法可以用來檢測一個物件是否含有特定的自身屬性;如果有返回true。否則返回false
// 和 in 運算子不同,該方法會忽略掉那些從原型鏈上繼承到的屬性。
if(oldObj.hasOwnProperty(prop)){
newObj[prop] = oldObj[prop]
}
}
return newObj;
}
複製程式碼
- 使用Object.assign()
var pj = { a: {a: "彭彭", b: 39} };
var pj1 = Object.assign({}, obj);
pj1.a.a = "wade";
console.log(pj.a.a); //wade
複製程式碼
注意:當object只有一層的時候,是深拷貝
var pj = { a: {a: "彭彭", b: 39} };
var pj1 = Object.assign({}, obj);
pj1.a.a = "wade";
console.log(pj.a.a); //wade
複製程式碼
- 陣列的淺拷貝
// 第一種
let arr = [1, 3, {
username: '彭彭'
}];
let arr2=arr.concat();
arr2[2].username = '君';
console.log(arr[2].username); // 君
// 第二種
let arr = [1, 3, {
username: ' 彭彭'
}];
let arr3 = arr.slice();
arr3[2].username = '君';
console.log(arr[2].username); // 君
// 一般很少用到陣列的拷貝。
// 陣列淺拷貝和物件是一樣的
複製程式碼
原陣列的元素會按照下述規則拷貝:
- 如果該元素是個物件引用(不是實際的物件),slice 會拷貝這個物件引用到新的陣列裡。兩個物件引用都引用了同一個物件。如果被引用的物件發生改變,則新的和原來的陣列中的這個元素也會發生改變。
- 對於字串、數字及布林值來說(不是 String、Number 或者 Boolean 物件),slice 會拷貝這些值到新的陣列裡。在別的陣列裡修改這些字串或數字或是布林值,將不會影響另一個陣列。
四,深拷貝
- JSON.parse(JSON.stringify())
var pj = {
name: '彭彭',
handle: function(){}
};
var deepPj = JSON.parse(JSON.stringify(pj)); // {name: "彭彭"}。。這種方式弊端在於無法拷貝方法。
複製程式碼
- 自覺手動封裝了
function deepCopy(oldObj) {
var newObj;
var oldObjType = Object.prototype.toString.call(oldObj).slice(8, -1);
if(oldObjType === 'Object'){
newObj = {};
}else if(oldObjType === 'array'){
newObj = [];
}else{
return oldObj;
}
for(let prop in oldObj){
let value = oldObj[prop];
let valueType = Object.prototype.toString.call(value).slice(8, -1);
if (valueType === 'Object' || valueType = 'Array') {
deepCopy(value);
} else {
newObj[prop] = value;
}
}
return newObj;
}
複製程式碼
- 借用第三方庫 函式庫lodash
- 該函式庫也有提供_.cloneDeep用來做 Deep Copy
var _ = require('lodash');
var obj1 = {
a: 1,
b: { f: { g: 1 } },
c: [1, 2, 3]
};
var obj2 = _.cloneDeep(obj1);
console.log(obj1.b.f === obj2.b.f); // false
複製程式碼