直接上代码是我的风格
一,赋值
- 基本数据类型的赋值
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
复制代码