一、曾经在读JQ源码的时候,对深拷贝算是有了一点的理解。我们在项目中是不是经常会遇到这样的问题呢?

后台返回一个数组对象(引用类型).次数在页面渲染中需要对部分数据进行处理 比如:银行卡62345092534 (这么长) 但在页面显示的时候,

只显示中国银行(3118)但是传给后台的时候。又要传623445242整个号码,我们也许会把var oldData = res.data;

但是我们发现两个数据都变了? 这是为什么呢? 其实就是一个深浅拷贝的问题。

二、浅拷贝

比如数组,对象,这样的引用类型。

var arr = ['js','html'];
var oldArr = arr;
oldArr[0] = 'css';
console.log(arr); // ['css','html']
/*
这其实是一个地址的引用。 相当于他们赋值的是指针。
*/
//在数组的方式中可以有两种方式来避免这种问题
//1.slice
var b = ['vue','react'];
var oldB = b.slice(0);
b[0] = 'angular';
console.log(b); //['angular','react']
console.log(oldB); // ['vue','react']
//2.concat();
var c = ['d3','three','webgl'];
var oldC = c.concat([]);
c[0] = 'earthgL';
console.log(c,oldC); // "earthgL", "three", "webgl"] ["d3", "three", "webgl"]

对象的浅复制也是一个道理。是对地址的引用而已。

 var obj = {
name:"前端",
age:"10"
}
var oldObj = obj;
obj.name = "html + css + js";
console.log(oldObj); //{name: "html + css + js", age: "10"}

三、深拷贝。

1.简单来说 深拷贝就事创建了一个新的内存空间。 他们不在会公用同一个内存空间。是两个完全独立的对象或数组。

var defaults = {
name: 'quber',
age: [1, 2, 3, 4],
child: [
{ name: 'qubernet', fun: function () { return 1; } },
{ name: 'qubernet1', fun: function () { return 2; } }
]
};
var newDefaults = $.extend(true, {},defaults );
console.log(JSON.stringify(newDefaults ));

2.JQ深拷贝源码部分

jQuery.extend = jQuery.fn.extend = function() {

    var options, name, src, copy, copyIsArray, clone,
target = arguments[0] || {},
i = 1,
length = arguments.length,
deep = false;
/*
变量 options:指向某个源对象。
变量 name:表示某个源对象的某个属性名。
变量 src:表示目标对象的某个属性的原始值。
变量 copy:表示某个源对象的某个属性的值。
变量 copyIsArray:指示变量 copy 是否是数组。
变量 clone:表示深度复制时原始值的修正值。
变量 target:指向目标对象,申明时先临时用第一个参数值。
变量 i:表示源对象的起始下标,申明时先临时用第二个参数值。
变量 length:表示参数的个数,用于修正变量 target。
变量 deep:指示是否执行深度复制,默认为 false。 ps:源对象指的是把自己的值付给别人的对象;目标对象指的是被源对象赋值的对象
*/ // 如果第一个参数传入的是布尔值
if ( typeof target === "boolean" ) {
deep = target;//设置deep变量,确定是深拷贝还是浅拷贝
target = arguments[1] || {};//将目标对象设为第二个参数值。
i = 2;//源对象的起始下标设为2(即从第三个参数开始算源对象)
} // Handle case when target is a string or something (possible in deep copy)
//嗯,原英文解释的很清楚
if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
target = {};
} // 如果没有目标对象,那么目标对象就是jquery对象
if ( length === i ) {
target = this;
--i;
} 拷贝的核心部分代码
for ( ; i < length; i++ ) {//遍历源对象
// Only deal with non-null/undefined values
if ( (options = arguments[ i ]) != null ) {//options就是源对象
// Extend the base object
for ( name in options ) {//遍历源对象的属性名
src = target[ name ];//获取目标对象上,属性名对应的属性
copy = options[ name ];//获取源对象上,属性名对应的属性 // 如果复制值copy 与目标对象target相等,
//为了避免深度遍历时死循环,因此不会覆盖目标对象的同名属性。
if ( target === copy ) {
continue;
} //递归地将源对象上的属性值合并到目标对象上
//如果是深拷贝,且待拷贝的对象存在,且是普通对象或是数组
//这一个判断条件非常关键,这正是之前疑问的症结
//首先,普通对象的定义是:通过 "{}" 或者 "new Object" 创建的
//回到之前的疑问,目标对象tobeCloned的属性o对象的obj不是普通对象,也不是数组,所以程序不会走到下面的分支
if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
if ( copyIsArray ) {
//如果是数组
copyIsArray = false;
clone = src && jQuery.isArray(src) ? src : []; } else {
clone = src && jQuery.isPlainObject(src) ? src : {};
} // 递归地拷贝
target[ name ] = jQuery.extend( deep, clone, copy ); } else if ( copy !== undefined ) {
//会走到这个分支,这个分支的处理很暴力,就是把源对象的属性,直接赋给源对象。
//对于上文中tobeCloned对象的属性o,没有进一步递归地拷贝,而是直接把引用赋给源对象
//所以改变tobeCloned的o属性时,目标对象的o属性也被改变了。
target[ name ] = copy;
}
}
}
} // Return the modified object
return target;
};

3.SE6提供的深拷贝的方法Object.assign(); (前提是没有属性对象)

四、总结。

简单来说:浅拷贝就是多个变量共用一个地址,深拷贝就是创建了多个内存空间。 (希望对你有帮助)

js 中引用类型 的深拷贝 和 浅拷贝的区别的更多相关文章

  1. 探究JS中对象的深拷贝和浅拷贝

    深拷贝和浅拷贝的区别 在讲深拷贝和浅拷贝的区别之前,回想一下我们平时拷贝一个对象时是怎么操作的?是不是像这样? var testObj1 = {a: 1, b:2}, testObj2=testObj ...

  2. 在js中如何区分深拷贝与浅拷贝?

    一.自我理解 简单来讲就是:深拷贝层层拷贝,浅拷贝只拷贝第一层. 在深拷贝中,新对象中的更改不会影响原对象,而在浅拷贝中,新对象中的更改,原对象中也会跟着改. 在深拷贝中,原对象与新对象不共享相同的属 ...

  3. Python中复制、深拷贝和浅拷贝的区别

    深拷贝定义(deepcopy) 在Python中,由于一切皆对象,所以任何变量都可以被引用,也即可以被赋值给任何变量.但是在Python中,给变量赋值,是区分的,一般情况下,Python中的变量赋值都 ...

  4. C#中??和?分别是什么意思? 在ASP.NET开发中一些单词的标准缩写 C#SESSION丢失问题的解决办法 在C#中INTERFACE与ABSTRACT CLASS的区别 SQL命令语句小技巧 JQUERY判断CHECKBOX是否选中三种方法 JS中!=、==、!==、===的用法和区别 在对象比较中,对象相等和对象一致分别指的是什么?

    C#中??和?分别是什么意思? 在C#中??和?分别是什么意思? 1. 可空类型修饰符(?):引用类型可以使用空引用表示一个不存在的值,而值类型通常不能表示为空.例如:string str=null; ...

  5. 【python测试开发栈】—理解python深拷贝与浅拷贝的区别

    内存的浅拷贝和深拷贝是面试时经常被问到的问题,如果不能理解其本质原理,有可能会答非所问,给面试官留下不好的印象.另外,理解浅拷贝和深拷贝的原理,还可以帮助我们理解Python内存机制.这篇文章将会通过 ...

  6. Python 深拷贝和浅拷贝的区别

    python的复制,深拷贝和浅拷贝的区别    在python中,对象赋值实际上是对象的引用.当创建一个对象,然后把它赋给另一个变量的时候,python并没有拷贝这个对象,而只是拷贝了这个对象的引用  ...

  7. 关于js中for in和foreach in的区别

    js 中for in 和foreach in的区别 两个的作用都用来遍历对象,但为什么有了for in语句了还要foreach in语句呢,后来看了下foreach in开发的文档,foreach i ...

  8. js中加“var”和不加“var”的区别

    JavaScript 拥有动态类型.这意味着相同的变量可用作不同的类型: var x // x 为 undefined var x = 6; // x 为数字 var x = "Bill&q ...

  9. JS中构造函数和普通函数有什么区别

    JS中构造函数有普通函数有什么区别? 1.一般规则 构造函数都应该以 一个大写字母开头,eg: function Person(){...} 而非构造函数则应该以一个小写字母开头,eg: functi ...

随机推荐

  1. -bash: fork: retry: Resource temporarily unavailable;centos6.5

    Last login: Wed Jun 18 14:04:11 2014 from 1.1.1.135 -bash: fork: retry: Resource temporarily unavail ...

  2. 最邻近规则分类(K-Nearest Neighbor)KNN算法

     自写代码: # Author Chenglong Qian from numpy import * #科学计算模块 import operator #运算符模块 def createDaraSet( ...

  3. PAT B1022 D进制的A+B (20 分)

    输入两个非负 10 进制整数 A 和 B (≤),输出 A+B 的 D (1)进制数. 输入格式: 输入在一行中依次给出 3 个整数 A.B 和 D. 输出格式: 输出 A+B 的 D 进制数. 输入 ...

  4. Python2.7-array

    array 模块,定义了 array 对象的一组数据,和 list 类似,只不过 array 对象的数据类型不能改变,和c/c++一样,主要用于打包和解包二进制数据,应该是用于网络通信较多 数据类型有 ...

  5. 同步IO和异步IO的区别

    首先一个IO操作其实分成了两个步骤:发起IO请求和实际的IO操作,同步IO和异步IO的区别就在于第二个步骤是否阻塞,如果实际的IO读写阻塞请求进程,那么就是同步IO,因此阻塞IO.非阻塞IO.IO服用 ...

  6. 2017-2018-2 20155231《网络对抗技术》实验八: WEB基础实验

    2017-2018-2 20155231<网络对抗技术>实验八:Web基础 实验要求: Web前端HTML(0.5分) 能正常安装.启停Apache.理解HTML,理解表单,理解GET与P ...

  7. ubuntu安装微信客户端

    安装linux微信: apt-get install git git clone https://github.com/geeeeeeeeek/electronic-wechat.git cd ele ...

  8. python语言程序设计2

    1, 代码高亮色彩体系 2, 缩进,一行代码开始前的空白区域,表达程序的格式框架 单层缩进,多层缩进 特点 概念,缩进是语法的一部分,缩进不正确的话可能会导致程序运行错误 用处(意义),是表达代码间包 ...

  9. 记录下安装ES过程中遇到的错误及解决

    1.集群配置 需要修改 cluster.name .node.name .network.host: 0.0.0.0[此处默认localhost].http.port: 9200 只要集群名相同,且机 ...

  10. zooland 新开源的RPC项目,希望大家在开发的微服务的时候多一种选择,让微服务开发简单,并且容易上手。

    zooland 我叫它动物园地,一个构思很长时间的一个项目.起初只是觉得各种通信框架都封装的很好了,但是就是差些兼容,防错,高可用.同时在使用上,不希望有多余的代码,像普通接口一样使用就可以了. 基于 ...