浅拷贝:浅拷贝只是复制了内存地址,如果原地址中的对象改变了,浅拷贝出来的对象也会相应改变。

深拷贝:开辟了一块新的内存存放地址和地址指向的对象,原地址的任何对象改变了,深拷贝出来的对象不变。

浅拷贝数组(只拷贝第一级数组):

1.直接遍历

var arr = [1,2,3,4];

function copy(arg){

  var newArr = [];

  for(var i = 0; i < arr.length; i++) {
newArr.push(arr[i]);
} return newArr;
} var newArry = copy(arr);
console.log(newArry);
newArry[0] = 10;
console.log(newArry); // [10,2,3,4]
console.log(arr) // [1,2,3,4]

2.slice

var arr = [1,2,3,4]
var copyArr = arr.slice();
copyArr[0] = 10;
console.log(copyArr); // [10,2,3,4]
console.log(arr); // [1,2,3,4]

slice(start,end),slice()方法返回一个数组中复制出来的元素组成新数组,start指起始元素下标,end指终止元素下标

当slice()不带任何参数时,默认返回一个和原数组一样的新数组

3.concat()

var arr = [1,2,3,4]
var copyArr = arr.concat();
copyArr[0] = 10;
console.log(copyArr); // [10,2,3,4]
console.log(arr); // [1,2,3,4]

array.concat(array1,array2,.......,arrayN),concat()方法用于连接两个或多个数组(不会改变原数组,返回被连接数组的副本)

然而如果第一级数组元素是对象或数组,上面三种方式都失效:

var arr = [
{number:1},
{number:2},
{number:3} ]
var copyArr = arr.slice();
copyArr[0].number = 10;
console.log(copyArr); // [{number: 100}, { number: 2 },{ number: 3 }]
console.log(arr); // [{number: 100}, { number: 2 }, { number: 3 }]

浅拷贝对象(如果对象中的值不为数组或对象)

1.直接遍历

  var obj = {
name: "张三",
job: "学生"
} function copy (arg) {
let newobj = {}
for(let item in obj) {
newobj[item] = obj;
}
return newobj;
} var copyobj = copy(obj)
copyobj.name = "李四"
console.log(copyobj) // {name: '李四', job:: '学生'}
console.log(obj) // {name: '张三', job:: '学生'}

2.ES6的Object.assign

var obj = {
name: '张三',
job: '学生'
} var copyobj = Object.assign({},obj)
copyobj.name = '李四'
console.log(copyobj) // {name: '李四', job:: '学生'}
console.log(obj) // {name: '张三', job:: '学生'}

Object.assign:用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target),并返回合并后的target

用法: Object.assign(target, source1, source2); 所以 copyObj = Object.assign({}, obj); 这段代码将会把obj中的一级属性都拷贝到 {}中,然后将其返回赋给copyObj

3.ES6扩展运算符

var obj = {
name: '张三',
job: '学生'
} var copyobj = {...obj}
copyobj.name = '李四'
console.log(copyobj)
console.log(obj)

扩展运算符(...)用于取出参数对象的所有可遍历属性,拷贝到当前对象之中

深拷贝

JSON.stringify()和JSON.parse

用JSON.stringify把对象转成字符串,再用JSON.parse把字符串转成新的对象。

但是这种方法也有不少坏处,譬如它会抛弃对象的constructor。也就是深拷贝之后,不管这个对象原来的构造函数是什么,在深拷贝之后都会变成Object。

这种方法能正确处理的对象只有 Number, String, Boolean, Array, 扁平对象,即那些能够被 json 直接表示的数据结构。RegExp对象是无法通过这种方式深拷贝。

也就是说,只有可以转成JSON格式的对象才可以这样用,像function、undefined、symbol、循环引用的对象没办法转成JSON。

var obj1 = { fun: function(){ console.log(123) } };
var obj2 = JSON.parse(JSON.stringify(obj1));
console.log(typeof obj1.fun);
// 'function'
console.log(typeof obj2.fun);
// 'undefined' <-- 没复制

使用递归函数实现一个深拷贝的方法

function deepClone(obj) {
let objClone = Array.isArray(obj) ? [] : {};
if(obj && typeof obj === "object") {
for(key in obj) {
if(obj.hasOwnProperty(key)) {
if(obj[key] && typeof obj[key] === "object") {
objClone[key] = deepClone(obj[key]);
} else {
objClone[key] = obj[key];
}
}
}
}
return objClone
}

最新文章

  1. SOCKet 编程 简介
  2. Apache Spark源码走读之22 -- 浅谈mllib中线性回归的算法实现
  3. C++ 我想这样用(七)
  4. eclipse同时开两个tomcat
  5. Java中char占用几个字节
  6. cocos2dx 自己主动加入cpp文件到android.mk
  7. 关于通过id查询记录的一些总结
  8. 关于default的位置问题:default放在前面
  9. VSFTP服务——实验
  10. WPF 圖表控件 MetroChart
  11. 嵌入式Linux引导过程之1.1——Xloader的xloader.lds
  12. 【翻译】Siesta事件记录器入门
  13. DB2常见问题
  14. 文件的暂存(git add)
  15. 545. Boundary of Binary Tree二叉树的边界
  16. 使用Docker-Docker for Web Developers(2)
  17. Redis系列九:redis集群高可用
  18. 关于LINUX在中断(硬软)中不能睡眠的真正原因
  19. 智能引导式报错(Class file name must end with .class)
  20. 集合之hascode方法

热门文章

  1. 使用java applet通过签名访问客户端串口
  2. CSP学习之CryptoAPI初识
  3. python的传递实参
  4. canvas玩转微信红包
  5. mfc自动创建按钮消息处理并清除
  6. 基于ArcGIS Runtime 100.x 的移动应用程序开发框架 开源
  7. 禁止IOS双击上滑
  8. font not embeded
  9. raid管理
  10. CSS和文档流