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 css函数用法(判断标签是否拥有某属性)
May 28 Javascript
JavaScript中“+”的陷阱深刻理解
Dec 04 Javascript
基于jQuery实现的图片切换焦点图整理
Dec 07 Javascript
Vue.js快速入门教程
Sep 07 Javascript
Vue.js第二天学习笔记(vue-router)
Dec 01 Javascript
js模糊查询实例分享
Dec 26 Javascript
微信小程序中显示html格式内容的方法
Apr 25 Javascript
用原生JS实现简单的多选框功能
Jun 12 Javascript
node.js的Express服务器基本使用教程
Jan 09 Javascript
理理Vue细节(推荐)
Apr 16 Javascript
vue resource发送请求的几种方式
Sep 30 Javascript
Element Card 卡片的具体使用
Jul 26 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
解决FastCGI 进程超过了配置的活动超时时限的问题
2013/07/03 PHP
PHP扩展模块Pecl、Pear以及Perl的区别
2014/04/09 PHP
PHP中call_user_func_array回调函数的用法示例
2016/11/26 PHP
Yii2学习笔记之汉化yii设置表单的描述(属性标签attributeLabels)
2017/02/07 PHP
php curl简单采集图片生成base64编码(并附curl函数参数说明)
2019/02/15 PHP
jquery pagination插件实现无刷新分页代码
2009/10/13 Javascript
javascript cookie操作类的实现代码小结附使用方法
2010/06/02 Javascript
Javascript创建自定义对象 创建Object实例添加属性和方法
2012/06/04 Javascript
jQuery动态改变图片显示大小(修改版)的实现思路及代码
2013/12/24 Javascript
百度移动版的url编码解码示例
2014/04/29 Javascript
jquery仿百度经验滑动切换浏览效果
2015/04/14 Javascript
jQuery中$(function() {});问题详解
2015/08/10 Javascript
点击按钮出现60秒倒计时的简单js代码(推荐)
2016/06/07 Javascript
浅谈js中StringBuffer类的实现方法及使用
2016/09/02 Javascript
Vue中的异步组件函数实现代码
2018/07/20 Javascript
解决vue中修改export default中脚本报一大堆错的问题
2018/08/27 Javascript
Vue formData实现图片上传
2019/08/20 Javascript
简单了解前端渐进式框架VUE
2020/07/20 Javascript
js实现表格数据搜索
2020/08/09 Javascript
[01:11:02]Secret vs Newbee 2019国际邀请赛小组赛 BO2 第一场 8.15
2019/08/17 DOTA
Python 的 with 语句详解
2014/06/13 Python
Linux下使用python自动修改本机网关代码分享
2015/05/21 Python
Python实现批量读取图片并存入mongodb数据库的方法示例
2018/04/02 Python
使用Python实现租车计费系统的两种方法
2018/09/29 Python
Python求离散序列导数的示例
2019/07/10 Python
Pandas 重塑(stack)和轴向旋转(pivot)的实现
2019/07/22 Python
python多任务之协程的使用详解
2019/08/26 Python
flask/django 动态查询表结构相同表名不同数据的Model实现方法
2019/08/29 Python
Python的信号库Blinker用法详解
2020/12/31 Python
《姥姥的剪纸》教学反思
2014/02/25 职场文书
实习证明格式范文
2014/10/14 职场文书
党校学习个人总结
2015/02/15 职场文书
廉洁自律心得体会2016
2016/01/13 职场文书
聊聊JS ES6中的解构
2021/04/29 Javascript
MySQL 存储过程的优缺点分析
2021/05/20 MySQL
Spring事务管理下synchronized锁失效问题的解决方法
2022/03/31 Java/Android