所谓 深浅拷贝
对于仅仅是复制了引用(地址),换句话说,复制了之后,原来的变量和新的变量指向同一个东西,彼此之间的操作会互相影响,为 浅拷贝
而如果是在堆中重新分配内存,拥有不同的地址,但是值是一样的,复制后的对象与原来的对象是完全隔离,互不影响,为 深拷贝
 
深浅拷贝 的主要区别就是:复制的是引用(地址)还是复制的是实例。
 //浅复制
function shallowCopy(src){
var dst = {};
for(var key in src){
if(src.hasOwnProperty(key)){
dst[key] = src[key];
}
}
return dst;
} var obj = {
a : 1,
arr : [2,3]
};
var shallowObj = shallowCopy(obj);
console.log(obj === shallowObj); //false
shallowObj.arr[1] = 5;
console.log(obj.arr[1]); // = 5
console.log(obj); //{ a: 1, arr: [ 2, 5 ] }
console.log(shallowObj); //{ a: 1, arr: [ 2, 5 ] }
//利用 递归 来实现深复制,对属性中所有引用类型的值,遍历到是基本类型的值为止。
function deepCopy(src){
if(!src && typeof src !== 'object'){
return;
}
var dst = src.constructor === Array ? []:{};
for(var key in src){
if(src.hasOwnProperty(key)){
if(src[key] && typeof src[key] === 'object'){
dst[key] = src[key].constructor === Array ? []:{};
dst[key] = deepCopy(src[key]); //递归
}else{
dst[key] = src[key];
}
}
}
return dst;
} var a = {
name:"jack",
age:20
};
var b = deepCopy(a);
console.log(a === b); //false
a.age = 30;
console.log(a); //{ name: 'jack', age: 30 }
console.log(b); //{ name: 'jack', age: 20 }

深拷贝浅拷贝问题探究:

1. Array 的 slice 和 concat 方法

两者都会返回一个新的数组实例。

//slice
var a = [1,2,3];
var b = a.slice(); //slice
console.log(b === a);
a[0] = 4;
console.log(a); //[ 4, 2, 3 ]
console.log(b); //[ 1, 2, 3 ] //concat
var a = [1,2,3];
var b = a.concat(); //concat
console.log(b === a);
a[0] = 4;
console.log(a); //[ 4, 2, 3 ]
console.log(b); //[ 1, 2, 3 ]

看起来很像深拷贝,但实际上不是!!!

//slice
var a = [[1,2,3],4,5];
var b = a.slice();
console.log(a === b); //false
a[0][0] = 6;
console.log(a); //[ [ 6, 2, 3 ], 4, 5 ]
console.log(b); //[ [ 6, 2, 3 ], 4, 5 ] //concat
var a = [[1,2,3],4,5];
var b = a.concat(); //concat
console.log(b === a); //false
a[0][0] = 6;
console.log(a); //[ [ 6, 2, 3 ], 4, 5 ]
console.log(b); //[ [ 6, 2, 3 ], 4, 5 ]

Array的 slice 和 concat 方法 并不是 真正的深拷贝,他们其实是浅拷贝。   递归复制是无法完成的。

2. jQuery中的 extend 复制方法

可以用来扩展对象,这个方法可以传入一个参数:deep(true or false),表示是否执行深复制(如果是深复制则会执行递归复制)。

//jQuery环境下运行
//深复制
var obj = {
name:'xixi',
age:20,
company : { name : '腾讯', address : '深圳'}
};
var obj_extend = $.extend(true,{}, obj); //extend方法,第一个参数为true,为深拷贝,为false,或者没有为浅拷贝。
console.log(obj === obj_extend); //false
obj.company.name = "ali";
obj.name = "hei";
console.log(obj); //{name:'hei',age:20,company : { name : 'ali', address : '深圳'} }
console.log(obj_extend); //{name:'xixi',age:20,company : { name : '腾讯', address : '深圳'} }

//jQuery环境下运行
//浅复制
var obj = {
    name:"xixi",
age:20,
company : { name : '腾讯', address : '深圳'}
};
var obj_extend = $.extend(false,{}, obj); //extend方法,第一个参数为true,为深拷贝,为false,或者没有为浅拷贝。
console.log(obj === obj_extend); //false
obj.name = "heihei";
console.log(obj); //{name:'heihei',age:20,company : { name : '腾讯', address : '深圳'}
console.log(obj_extend); //{name:'xixi',age:20,company : { name : '腾讯', address : '深圳'}

总结:Array 的 slice 和 concat 方法 和 jQuery 中的 extend 复制方法,他们都会复制第一层的值,对于 第一层 的值都是 深拷贝,而到 第二层 的时候 Array 的 slice 和 concat 方法就是 复制引用 ,jQuery 中的 extend 复制方法 则 取决于 你的 第一个参数, 也就是是否进行递归复制。所谓第一层 就是 key 所对应的 value 值是基本数据类型,也就像上面栗子中的name、age,而对于 value 值是引用类型 则为第二层,也就像上面例子中的 company。

3. JSON 对象的 parse 和 stringify

JOSN 对象中的 stringify 可以把一个 js 对象序列化为一个 JSON 字符串,parse 可以把 JSON 字符串反序列化为一个 js 对象,这两个方法实现的是深拷贝

var obj = {
name:'xixi',
age:20,
company : { name : '腾讯', address : '深圳'}
};
var obj_json = JSON.parse(JSON.stringify(obj));
console.log(obj === obj_json); //false
obj.company.name = "ali";
obj.name = "hei";
console.log(obj); //{ name: 'hei', age: 20, company: { name: 'ali', address: '深圳' } }
console.log(obj_json); //{ name: 'xixi', age: 20, company: { name: '腾讯', address: '深圳' } }

js中的深拷贝和浅拷贝2的更多相关文章

  1. js 中的深拷贝与浅拷贝

    在面试中经常会问到js的深拷贝和浅拷贝,也常常让我们手写,下面我们彻底搞懂js的深拷贝与浅拷贝. 在js中 Array 和 Object  这种引用类型的值,当把一个变量赋值给另一个变量时,这个值得副 ...

  2. js中的深拷贝与浅拷贝

    对象的深拷贝于浅拷贝 对于基本类型,浅拷贝过程就是对值的复制,这个过程会开辟出一个新的内存空间,将值复制到新的内存空间.而对于引用类型来书,浅拷贝过程就是对指针的复制,这个过程并没有开辟新的堆内存空间 ...

  3. js 中的 深拷贝与浅拷贝

    js在平时的项目中,赋值操作是最多的:比如说: var person1 = { name:"张三", age:18, sex:"male", height:18 ...

  4. JS中的深拷贝和浅拷贝

    浅拷贝 浅拷贝是拷贝第一层的拷贝 使用Object.assign解决这个问题. let a = { age: 1 } let b = Object.assign({}, a) a.age = 2 co ...

  5. JS对象复制(深拷贝、浅拷贝)

    如何在 JS 中复制对象 在本文中,我们将从浅拷贝(shallow copy)和深拷贝(deep copy)两个方面,介绍多种 JS 中复制对象的方法. 在开始之前,有一些基础知识值得一提:Javas ...

  6. javascript中的深拷贝与浅拷贝

    javascript中的深拷贝与浅拷贝 基础概念 在了解深拷贝与浅拷贝的时候需要先了解一些基础知识 核心知识点之 堆与栈 栈(stack)为自动分配的内存空间,它由系统自动释放: 堆(heap)则是动 ...

  7. 浅谈Java中的深拷贝和浅拷贝(转载)

    浅谈Java中的深拷贝和浅拷贝(转载) 原文链接: http://blog.csdn.net/tounaobun/article/details/8491392 假如说你想复制一个简单变量.很简单: ...

  8. C语言中的深拷贝和浅拷贝

    //C语言中的深拷贝和浅拷贝 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> #inc ...

  9. 浅谈Java中的深拷贝和浅拷贝

    转载: 浅谈Java中的深拷贝和浅拷贝 假如说你想复制一个简单变量.很简单: int apples = 5; int pears = apples; 不仅仅是int类型,其它七种原始数据类型(bool ...

随机推荐

  1. Spark-内存管理调优

    这篇文章主要是对官网内容学习过程的总结,大部分是原文,加上自己的学习笔记!!! spark 2.0+内存模型 调优内存使用时需要考虑三个因素: 对象使用的内存数量(您可能希望您的整个数据集都能装入内存 ...

  2. Activiti 接收任务活动

    流程中往往需要特定人接受任务并进行一定操作才能继续进行下去. 代码如下 import java.io.InputStream; import org.activiti.engine.ProcessEn ...

  3. [转]Visual Studio 2010单元测试(2)--运行测试并查看代码覆盖率

    Visual Studio 2010 单元测试--运行测试并查看代码覆盖率 运行测试并查看代码覆盖率对程序集中的代码运行测试时,可以通过收集代码覆盖率数据来查看正在测试的项目代码部分. 运行测试并查看 ...

  4. Python pylint的安装和使用

    Pylint 是一个 Python 代码分析工具,它分析 Python 代码中的错误,查找不符合代码风格标准和有潜在问题的代码. Pylint 是一个 Python 工具,除了平常代码分析工具的作用之 ...

  5. ajaxfileupload 上传使用demo

    1.添加js引用 <script src="JS/jquery-1.4.2.min.js" type="text/javascript"></ ...

  6. SQL server插入数据后,获取自增长字段的值

      ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 insert into Tb_People(uname,er ...

  7. gitlab merge request

    分支提了mr之后, 又有commit 不用重新提mr,mr中会自动更新 要保证项目下的.git目录中有hooks这个目录(如果是从github迁移到gitlab的项目, 可能没有这个目录, 导致mr不 ...

  8. 原生JS实现动态时钟(优化)

    <!doctype html> <html> <head> <meta charset="utf-8"> <title> ...

  9. WPF DataGrid动态生成列的单元格背景色绑定

    <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Column.DisplayInde ...

  10. KOA 学习(一)

    一.安装KOA 用npm下载KOA 就会在koa文件夹下生成 二.输出hello,world 我下载的KOA版本号是2.0.1 const Koa = require('koa'); const ap ...