js对象浅拷贝和深拷贝详解


Posted in Javascript onSeptember 05, 2016

本文为大家分享了JavaScript对象的浅拷贝和深拷贝代码,供大家参考,具体内容如下

1.浅拷贝

拷贝就是把父对像的属性,全部拷贝给子对象。

下面这个函数,就是在做拷贝:

var Chinese = {
nation:'中国'
}
var Doctor = {

career:'医生'
}

function extendCopy(p) {


var c = {};


for (var i in p) { 



c[i] = p[i];


}


c.uber = p;


return c;
 }

使用的时候,这样写:

var Doctor = extendCopy(Chinese);
Doctor.career = '医生';
alert(Doctor.nation); // 中国

但是,这样的拷贝有一个问题。那就是,如果父对象的属性等于数组或另一个对象,那么实际上,子对象获得的只是一个内存地址,而不是真正拷贝,因此存在父对象被篡改的可能。

请看,现在给Chinese添加一个”出生地”属性,它的值是一个数组。

Chinese.birthPlaces = ['北京','上海','香港'];

通过extendCopy()函数,Doctor继承了Chinese。

var Doctor = extendCopy(Chinese);

然后,我们为Doctor的”出生地”添加一个城市:

Doctor.birthPlaces.push('厦门');

看一下输入结果

alert(Doctor.birthPlaces); //北京, 上海, 香港, 厦门
alert(Chinese.birthPlaces); //北京, 上海, 香港, 厦门

结果是两个的出生地都被改了。

所以,extendCopy() 只是拷贝了基本类型的数据,我们把这种拷贝叫做“浅拷贝”。

2.深拷贝

因为浅深拷有如此弊端所以我们接下来看一下深拷贝

所谓”深拷贝”,就是能够实现真正意义上的数组和对象的拷贝。它的实现并不难,只要递归调用”浅拷贝”就行了。

function deepCopy(p, c) {

var c = c || {};


for (var i in p) {



if (typeof p[i] === 'object') {




c[i] = (p[i].constructor === Array) ? [] : {};




deepCopy(p[i], c[i]);



} else {




 c[i] = p[i];



}


}


return c;

}

看一下使用方法:

var Doctor = deepCopy(Chinese);

现在,给父对象加一个属性,值为数组。然后,在子对象上修改这个属性:

Chinese.birthPlaces = ['北京','上海','香港'];
Doctor.birthPlaces.push('厦门');

alert(Doctor.birthPlaces); //北京, 上海, 香港, 厦门
alert(Chinese.birthPlaces); //北京, 上海, 香港

这样就完成了拷贝;

$.extend()

jquery 中$.extend()如同。

$.extend( [deep ], target, object1 [, objectN ] )

 •deep
类型: Boolean
如果是true,合并成为递归(又叫做深拷贝)。
 •target
类型: Object
对象扩展。这将接收新的属性。
 •object1
类型: Object
一个对象,它包含额外的属性合并到第一个参数.
 •objectN
类型: Object
包含额外的属性合并到第一个参数 

当我们提供两个或多个对象给$.extend(),对象的所有属性都添加到目标对象(target参数)。

如果只有一个参数提供给$.extend(),这意味着目标参数被省略。在这种情况下,jQuery对象本身被默认为目标对象。这样,我们可以在jQuery的命名空间下添加新的功能。这对于插件开发者希望向 jQuery 中添加新函数时是很有用的。

请记住,目标对象(第一个参数)将被修改,并且将通过$.extend()返回。然而,如果我们想保留原对象,我们可以通过传递一个空对象作为目标对象:

var object = $.extend({}, object1, object2);

在默认情况下,通过$.extend()合并操作不是递归的;如果第一个对象的属性本身是一个对象或数组,那么它将完全用第二个对象相同的key重写一个属性。这些值不会被合并。可以通过检查下面例子中 banana 的值,就可以了解这一点。然而,如果将 true 作为该函数的第一个参数,那么会在对象上进行递归的合并。

警告:不支持第一个参数传递 false 。

1. 合并两个对象,并修改第一个对象。

var object1 = {
 apple: 0,
 banana: { weight: 52, price: 100 },
 cherry: 97
};
var object2 = {
 banana: { price: 200 },
 durian: 100
};

// Merge object2 into object1
$.extend( object1, object2 );

// Assuming JSON.stringify - not available in IE<8
console.log( JSON.stringify( object1 ) );
//{"apple":0,"banana":{"price":200},"cherry":97,"durian":100}

2. 采用递归方式合并两个对象,并修改第一个对象。

var object1 = {
 apple: 0,
 banana: { weight: 52, price: 100 },
 cherry: 97
};
var object2 = {
 banana: { price: 200 },
 durian: 100
};

// Merge object2 into object1, recursively
$.extend( true, object1, object2 );

// Assuming JSON.stringify - not available in IE<8
console.log( JSON.stringify( object1 ) );
//{"apple":0,"banana":{"weight":52,"price":200},"cherry":97,"durian":100}

3. 合并 defaults 和 options 对象,并且不修改 defaults 对象。这是常用的插件开发模式。

var defaults = { validate: false, limit: 5, name: "foo" };
var options = { validate: true, name: "bar" };

// Merge defaults and options, without modifying defaults
var settings = $.extend( {}, defaults, options );


console.log(JSON.stringify( defaults ));
console.log(JSON.stringify( options ));
console.log(JSON.stringify( settings ));
//defaults -- {"validate":false,"limit":5,"name":"foo"}
//options -- {"validate":true,"name":"bar"}
//settings -- {"validate":true,"limit":5,"name":"bar"}

Javascript 判断对象是否相等

在Javascript中相等运算包括”==”,”===”全等,两者不同之处,不必多数,本篇文章我们将来讲述如何判断两个对象是否相等? 你可能会认为,如果两个对象有相同的属性,以及它们的属性有相同的值,那么这两个对象就相等。那么下面我们通过一个实例来论证下:

var obj1 = {
  name: "Benjamin",
  sex : "male"
}

var obj2 = {
  name: "Benjamin",
  sex : "male"
}

//Outputs: false
console.log(obj1 == obj2);

//Outputs: false
console.log(obj1 === obj2);

通过上面的例子可以看到,无论使用”==”还是”===”,都返回false。主要原因是基本类型string,number通过值来比较,而对象(Date,Array)及普通对象通过指针指向的内存中的地址来做比较。看下面一个例子:

var obj1 = {
  name: "Benjamin",
  sex : "male"
};

var obj2 = {
  name: "Benjamin",
  sex : "male"
};

var obj3 = obj1;

//Outputs: true
console.log(obj1 == obj3);

//Outputs: true
console.log(obj1 === obj3);

//Outputs: false
console.log(obj2 == obj3);

//Outputs: false
console.log(obj2 === obj3);

上例返回true,是因为obj1和ob3的指针指向了内存中的同一个地址。和面向对象的语言(Java/C++)中值传递和引用传递的概念相似。 因为,如果你想判断两个对象是否相等,你必须清晰,你是想判断两个对象的属性是否相同,还是属性对应的值是否相同,还是怎样?

function person(name) { 
  this.name=name; 
} 

var p1 = new person("p1"); 
var p2 = new person("p2"); 

console.log(p1 == p2); //false 

person.prototype.sayHi = function() { 
  // do sayHi here 
} 

console.log(p1.sayHi() == p2.sayHi()); //true 
console.log(p1.sayHi() === p2.sayHi()); //true

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jquery常用技巧及常用方法列表集合
Apr 06 Javascript
禁止IE用右键的JS代码
Dec 30 Javascript
jquery对单选框,多选框,文本框等常见操作小结
Jan 08 Javascript
href下载文件根据id取url并下载
May 28 Javascript
onclick和onblur冲突问题的快速解决方法
Apr 28 Javascript
Javascript动画效果(4)
Oct 11 Javascript
基于vue.js 2.x的虚拟滚动条的示例代码
Jan 23 Javascript
vue 解决form表单提交但不跳转页面的问题
Oct 30 Javascript
js实现div色块拖动录制
Jan 16 Javascript
js实现特别简单的钟表效果
Sep 14 Javascript
Vue获取微博授权URL代码实例
Nov 04 Javascript
nestjs返回给前端数据格式的封装实现
Feb 22 Javascript
JS实现隐藏同级元素后只显示JS文件内容的方法
Sep 04 #Javascript
jQuery实现智能判断固定导航条或侧边栏的方法
Sep 04 #Javascript
angularjs实现文字上下无缝滚动特效代码
Sep 04 #Javascript
jQuery实现为LI列表前3行设置样式的方法【2种方法】
Sep 04 #Javascript
JS实现屏蔽网页右键复制及ctrl+c复制的方法【2种方法】
Sep 04 #Javascript
jQuery实现的自动加载页面功能示例
Sep 04 #Javascript
jQuery简单实现中间浮窗效果
Sep 04 #Javascript
You might like
浅谈Eclipse PDT调试PHP程序
2014/06/09 PHP
php中使用gd库实现下载网页中所有图片
2015/05/12 PHP
PHP Static延迟静态绑定用法分析
2016/03/16 PHP
php微信公众号开发之答题连闯三关
2018/10/20 PHP
用js实现键盘方向键翻页功能的代码
2007/06/03 Javascript
12个非常有创意的JavaScript小游戏
2010/03/18 Javascript
复制Input内容的js代码_支持所有浏览器,修正了Firefox3.5以上的问题
2010/06/21 Javascript
jquery插件制作教程 txtHover
2012/08/17 Javascript
JQ获取动态加载的图片大小的正确方法分享
2013/11/08 Javascript
Javascript学习笔记之数组的构造函数
2014/11/23 Javascript
招聘网站基于jQuery实现自动刷新简历
2015/05/10 Javascript
jQuery+Ajax+PHP+Mysql实现分页显示数据实例讲解
2015/09/27 Javascript
基于MVC4+EasyUI的Web开发框架形成之旅之界面控件的使用
2015/12/16 Javascript
JS解决移动web开发手机输入框弹出的问题
2017/03/31 Javascript
JavaScript登录验证基础教程
2017/11/01 Javascript
ionic3实战教程之随机布局瀑布流的实现方法
2017/12/28 Javascript
使用async、enterproxy控制并发数量的方法详解
2018/01/02 Javascript
详解React中setState回调函数
2018/06/14 Javascript
使用 webpack 插件自动生成 vue 路由文件的方法
2019/08/20 Javascript
[01:38:19]夜魇凡尔赛茶话会 第五期
2021/03/11 DOTA
Python排序搜索基本算法之希尔排序实例分析
2017/12/09 Python
Python编程中flask的简介与简单使用
2018/12/28 Python
Python实现随机取一个矩阵数组的某几行
2019/11/26 Python
布隆过滤器的概述及Python实现方法
2019/12/08 Python
python 成功引入包但无法正常调用的解决
2020/03/09 Python
python求前n个阶乘的和实例
2020/04/02 Python
pandas分批读取大数据集教程
2020/06/06 Python
python3中数组逆序输出方法
2020/12/01 Python
HTML5中drawImage用法分析
2014/12/01 HTML / CSS
德国家具在线:Fashion For Home
2017/03/11 全球购物
New Balance美国官网:运动鞋和健身服装
2017/04/11 全球购物
简单租房协议书范本
2014/08/20 职场文书
2014党支部对照检查材料思想汇报
2014/10/05 职场文书
实习科室评语
2015/01/04 职场文书
因身体原因离职的辞职信范文
2015/05/12 职场文书
团结主题班会
2015/08/13 职场文书