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 相关文章推荐
javascript的回调函数应用示例
Feb 20 Javascript
javascript常用正则表达式汇总
Jul 31 Javascript
利用CSS3在Angular中实现动画
Jan 15 Javascript
js实现网页图片延时加载 提升网页打开速度
Jan 26 Javascript
Bootstrap进度条组件知识详解
May 01 Javascript
快速解决Canvas.toDataURL 图片跨域的问题
May 10 Javascript
Vue的Class与Style绑定的方法
Sep 01 Javascript
JavaScript运行机制实例分析
Apr 11 Javascript
在vue中实现禁止回退上一步,路由不存历史记录
Jul 22 Javascript
webstorm建立vue-cli脚手架的傻瓜式教程
Sep 22 Javascript
如何用JS实现简单的数据监听
May 06 Javascript
JS的深浅复制详细
Oct 16 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
第五节 克隆 [5]
2006/10/09 PHP
PHP性能优化 产生高度优化代码
2011/07/22 PHP
Symfony2 session用法实例分析
2016/02/04 PHP
thinkPHP基于ajax实现的菜单与分页示例
2016/07/12 PHP
PHP利用正则表达式将相对路径转成绝对路径的方法示例
2017/02/28 PHP
PHP实现下载远程图片保存到本地的方法
2017/06/19 PHP
ThinkPHP实现转换数据库查询结果数据到对应类型的方法
2017/11/16 PHP
基于jQuery的烟花效果(运动相关)点击屏幕出烟花
2012/06/14 Javascript
创建自己的jquery表格插件
2015/11/25 Javascript
js仿百度登录页实现拖动窗口效果
2016/03/11 Javascript
简单实现node.js图片上传
2016/12/18 Javascript
layui选项卡效果实现代码
2017/05/19 Javascript
在Vue组件中使用 TypeScript的方法
2018/02/28 Javascript
vue.js 实现评价五角星组件的实例代码
2018/08/13 Javascript
在vue中使用express-mock搭建mock服务的方法
2018/11/07 Javascript
jQuery三组基本动画与自定义动画操作实例总结
2020/05/09 jQuery
简单的抓取淘宝图片的Python爬虫
2014/12/25 Python
Python编程中的文件操作攻略
2015/10/16 Python
Python3.6日志Logging模块简单用法示例
2018/06/14 Python
Python 查找list中的某个元素的所有的下标方法
2018/06/27 Python
一文了解Python并发编程的工程实现方法
2019/05/31 Python
pyqt 实现QlineEdit 输入密码显示成圆点的方法
2019/06/24 Python
在keras中获取某一层上的feature map实例
2020/01/24 Python
python global和nonlocal用法解析
2020/02/03 Python
Python实现遗传算法(二进制编码)求函数最优值方式
2020/02/11 Python
用CSS3绘制三角形的简单方法
2015/07/17 HTML / CSS
canvas 实现 github404动态效果的示例代码
2017/11/15 HTML / CSS
交通专业个人自荐信格式
2013/09/23 职场文书
大学军训感言600字
2014/02/25 职场文书
2014党员学习《反腐倡廉警示教育读本》思想汇报
2014/09/13 职场文书
乡领导班子四风问题对照检查材料
2014/09/25 职场文书
运动会广播稿20字
2015/08/19 职场文书
Python requests库参数提交的注意事项总结
2021/03/29 Python
Mysql数据库索引面试题(程序员基础技能)
2021/05/31 MySQL
Python 多线程处理任务实例
2021/11/07 Python
教你在 Java 中实现 Dijkstra 最短路算法的方法
2022/04/08 Java/Android