javascript中的浅拷贝和深拷贝 分类: JavaScript 2015-05-07 15:29 831人阅读 评论(1) 收藏
1.js对象浅拷贝
简单的赋值就是浅拷贝。因为对象和数组在赋值的时候都是引用传递。赋值的时候只是传递一个指针。
看下面的实例代码:
var a = [1,2,3];
var b =a ;
var test = {name:'xiaohong', age:15};
var c = test;
console.log(a);
console.log(b);
console.log(test);
console.log('-------------------');
b[0] =5;
c.age = 16;
console.log(a);
console.log(b);
console.log(test);
console.log(c);
结果如下:
浅拷贝很容易,但是很多时候我们需要原样的把数组或者对象复制一份,在修改值的时候,不改变初始对象的值。这个时候就需要使用深拷贝。
2.js对象深拷贝
因为对象相对较为复杂,所以我们先来看对数组的深拷贝的问题。
数组的深拷贝
//深拷贝
var a = [1,2,3];
var deepArry = [];
/**
* @param 被复制数组
* @param 新数组
*/
function deepCopy(arry1, arry2){
for(var i = 0,l= arry1.length;i<l;i++){
arry2[i] = arry1[i];
}
}
deepCopy(a,deepArry);
console.log(a);
console.log(deepArry);
deepArry[0] =5;
console.log(a);
console.log(deepArry);
运行的结果如下:
尝试多维数组
var b = [[1,2,3],4,5];
deepCopy(b,deepArry);
console.log(b);
console.log(deepArry);
deepArry[0][1] =5;
console.log(b);
console.log(deepArry);
发现结果不能满足要求,按照上面函数的复制,数组的第二维还是存放着对之前数组的引用。
对函数进行优化后的代码:
function deepCopy1(arry1, arry2){
var tempArry =[];
for(var i = 0,l= arry1.length;i<l;i++) {
//判断每一项是不是一个数组
if (arry1[i] instanceof Array ) {
deepCopy1(arry1[i], tempArry)
arry2[i] = tempArry;
}
else {
arry2[i] = arry1[i];
}
}
}
var b = [[1,2,3],4,5];
var c = [[1,[2,3]],4,5];
var d = [[1,2,3],4,[5,6,7]];
var deepArray = [];
deepCopy1(b, deepArry);
console.log(deepArry);
deepArry[0][0] =9; //修改deepArry的值
console.log(b);
console.log(deepArry);
deepArry.length=0; //初始化deepArray
deepCopy1(d,deepArry);
console.log(deepArry);
deepArry.length=0;
deepCopy1(c,deepArry);
console.log(c);
console.log(deepArry);
deepArry[0][1][0] = 99;
console.log(c);
console.log(deepArry);
运行结果如下:
对象的深拷贝
先来看一段代码:
function Test(){
this.name='xiaohong',
this.age=18,
this.run =function(){
console.log('run');
}
}
var test = new Test();
console.log(test.age);
test.run();
function ChilrTest () {
this.name = 'xiaogang',
this.age =15,
this.sing =function(){
console.log('sing');
}
};
ChilrTest.prototype = new Test();
var children = new ChilrTest();
children.sing();
children.run();
console.log('----childre的属性----') ;
for (var key in children){
console.log(key) ;
}
结果为:
当我们使用for …in 遍历一个对象的时候他会向上查询原型链上得属性。
我们可以使用对象的hasOwnProperty属性来过滤掉原型链上得属性
console.log('----childre的属性----') ;
for (var key in children){
if(children.hasOwnProperty(key)) {
console.log(key);
}
}
结果如下:
完整的clone一个对象的方法:
var cloneObject ={};
for (var key in children){
if(children.hasOwnProperty(key)) {
cloneObject[key] = children[key];
}
}
使用js提供的方法深拷贝一维数组
使用slice函数
var a =[1,2,3,4];
var b =[];
b =a.slice(0);
console.log(b);
b [0] = 9;
console.log(a);
console.log(b);
结果如下:
debugger listening on port 57289
[ 1, 2, 3, 4 ]
[ 1, 2, 3, 4 ]
[ 9, 2, 3, 4 ]
使用concat函数
var a =[1,2,3,4];
var b =[];
//b =a.slice(0);
b = a.concat([]);
console.log(b);
b [0] = 9;
console.log(a);
console.log(b);
结果如下:
debugger listening on port 57320
[ 1, 2, 3, 4 ]
[ 1, 2, 3, 4 ]
[ 9, 2, 3, 4 ]
jQuery中对数组的clone
使用jquery进行对象的复制
jQuery.extend( [ deep ], target , object1 [, objectN... ] )
请根据前面语法部分所定义的参数名称查找对应的参数。
参数描述
deep 可选/Boolean类型指示是否深度合并对象,默认为false。如果该值为true,且多个对象的某个同名属性也都是对象,则该”属性对象”的属性也将进行合并。
target Object类型目标对象,其他对象的成员属性将被复制到该对象上。 object1 可选/Object类型第一个被合并的对象。
objectN 可选/Object类型第N个被合并的对象。
示例代码:
var a = { k1: 1, k2: 2, k3: 3 };
var b = {k4:4, k5:5};
var c ;
c=$.extend(a); //将a对象复制到jquery对象上,并赋值给c
console.log('------------');
console.log(c === $); //c对象指向的是$对象,所以结果true
console.log(a === $); // false
console.log('------c------');
console.log(c.k2); //相当于$.k2
console.log('------c------');
console.log(c);
//c.k2 = 777;
console.log('------a------');
console.log(a);
console.log('------b------');
console.log(b);
console.log('------$------');
console.log($);
console.log($.k2);
结果:
看下面的一段代码:
var d = $.extend({}, a)
console.log(d);
d.k2 = 3456;
console.log(d);
console.log(a);
结果为:
可以知道,jquery中extend()不是复制引用,而是创建了新的对象
注意事项:
该函数复制的对象属性包括方法在内。此外,还会复制对象继承自原型中的属性(JS内置的对象除外)。
参数deep的默认值为false,你可以为该参数明确指定true值,但不能明确指定false值。简而言之,第一个参数不能为false值。
如果参数为null或undefined,则该参数将被忽略。
如果只为$.extend()指定了一个参数,则意味着参数target被省略。此时,target就是jQuery对象本身。通过这种方式,我们可以为全局对象jQuery添加新的函数。
如果多个对象具有相同的属性,则后者会覆盖前者的属性值。
看下面一段代码对数组对象进行拷贝:
var test = [1,2,34,];
console.log(test);
var contest= $.extend([],test);
console.log(contest);
contest.push(567);
console.log(test);
console.log(contest);
结果为:
版权声明:本文为博主原创文章,未经博主允许不得转载。
javascript中的浅拷贝和深拷贝 分类: JavaScript 2015-05-07 15:29 831人阅读 评论(1) 收藏的更多相关文章
- C语言中返回字符串函数的四种实现方法 2015-05-17 15:00 23人阅读 评论(0) 收藏
C语言中返回字符串函数的四种实现方法 分类: UNIX/LINUX C/C++ 2010-12-29 02:54 11954人阅读 评论(1) 收藏 举报 语言func存储 有四种方式: 1.使用堆空 ...
- C#中的线程(上)-入门 分类: C# 线程 2015-03-09 10:56 53人阅读 评论(0) 收藏
1. 概述与概念 C#支持通过多线程并行地执行代码,一个线程有它独立的执行路径,能够与其它的线程同时地运行.一个C#程序开始于一个单线程,这个单线程是被CLR和操作系统(也称为"主线 ...
- iOS中UITextField 使用全面解析 分类: ios技术 2015-04-10 14:37 153人阅读 评论(0) 收藏
//初始化textfield并设置位置及大小 UITextField *text = [[UITextField alloc]initWithFrame:CGRectMake(20, 20, 13 ...
- VS2010中使用命令行参数 分类: c/c++ 2014-07-11 22:24 634人阅读 评论(0) 收藏
在Linux下编程习惯了使用命令行参数,故使用VS2010时也尝试了一下. 新建项目,c++编写程序如下: #include<iostream> #include<fstream&g ...
- 【solr基础教程之九】客户端 分类: H4_SOLR/LUCENCE 2014-07-30 15:28 904人阅读 评论(0) 收藏
一.Java Script 1.由于Solr本身可以返回Json格式的结果,而JavaScript对于处理Json数据具有天然的优势,因此使用JavaScript实现Solr客户端是一个很好的选择. ...
- 浅谈声明与定义的区别 分类: C/C++ 2015-06-01 15:08 157人阅读 评论(4) 收藏
以下代码使用平台是VS2012. 清楚明白声明与定义是一名合格的程序猿的基本要求. 本人认为,C++编码过程中谈及"声明"和"定义"是因为我们要使用一个变量.类 ...
- SQL 分组 加列 加自编号 自编号限定 分类: SQL Server 2014-11-25 15:41 283人阅读 评论(0) 收藏
说明: (1)日期以年月形式显示:convert(varchar(7),字段名,120) , (2)加一列 (3)自编号: row_number() over(order by 字段名 desc) a ...
- PIE(二分) 分类: 二分查找 2015-06-07 15:46 9人阅读 评论(0) 收藏
Pie Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submissio ...
- iOS动画特效 分类: ios技术 2015-05-15 16:29 311人阅读 评论(0) 收藏
关于图层的几个坐标系. 对于ios来说,坐标系的(0,0)点在左上角,就是越往下,Y值越大.越往右,X值越大. 一个图层的frame,它是position,bounds,anchorPoint和tra ...
随机推荐
- linxu ssh 双端认证 不成功之authorized_keys
linxu ssh 双端认证 不成功之authorized_keys liunx双端认证可以让我们更简便的在两台服务器之间传输文件,配置暂且不说,网上有大部分的文章可以搜索到,今天我要说的是在不成功的 ...
- (转) MVC身份验证及权限管理-2
转自:http://www.cnblogs.com/ldp615/archive/2010/10/27/asp-net-mvc-forms-authentication-roles-authoriza ...
- IDEA14/Eclipse+Tomcat7热部署,jrebel6破解与eclipse配置
换了最新的eclipse,以前很多的插件都用不了,对于web开发的人来说,jrebel这种防重启神器必须要配备,防止修改类名.java文件.配置文件后的tomcat重启. 首先给一个下载地址: htt ...
- 1. Two Sum [Array] [Easy]
Given an array of integers, return indices of the two numbers such that they add up to a specific ta ...
- 解决Redis/Codis Connection with master lost(复制超时)问题
今天在线上环境中遇到了codis-server报警,按照常规处理流程进行处理,报错步骤如下: 首先将codis-slave的rdb文件移除,并重启codis-slave 在codis-dashbord ...
- Linux SSH无密码登录
Linux服务器常见的登录方式有两种:密码登录.秘钥登录.工作中我们最常使用的是用秘钥登录的方法,因为使用秘钥登录更高效.更安全. 如何实现SSH无密码登录: 原理:无密码ssh登录的主要操作为将本机 ...
- Code Review Checklist and Guidelines for C# Developers
Checklist1. Make sure that there shouldn't be any project warnings.2. It will be much better if Code ...
- subprocess.Popen 运行windows命令出现“句柄无效”报错的解决方法
在框架开发中遇到 subprocess执行多了,就会好句柄无效的问题,终于找到解决方案:如下,修改subprocess中的一点代码就好,也不知道这是不是Python 的bug因为,Python27时没 ...
- ASP.NET Core 2 学习笔记(二)生命周期
要了解程序的运行原理,就要先知道程序的进入点及生命周期.以往ASP.NET MVC的启动方式,是继承 HttpApplication 作为网站开始的进入点,而ASP.NET Core 改变了网站的启动 ...
- javascript js 完美解决 click 与 dblclick 冲突,并且不会导致click延迟
示例代码: marker.addEventListener("click", function(){ if (!window.markerClicked) { window.mar ...