JavaScript 数组的深度复制解析


Posted in Javascript onNovember 02, 2016

对于javascript而言,数组是引用类型,如果要想复制一个数组就要动脑袋想想了,因为包括concat、slice在内的函数,都是浅层复制。也就是说,对于一个二维数组来说,用concat来做复制,第二维的数组还是引用,修改了新数组同样会使旧数组发生改变。

    于是乎,想要写一个深度复制的函数,来帮助做组数的深度复制。

一般情况下,使用 “=” 可以实现赋值。但对于数组、对象、函数等这些引用类型的数据,这个符号就不好使了。

1. 数组的简单复制

1.1 简单遍历

最简单也最基础的方式,自然是循环处理。示例:

JavaScript

function array_copy(arr) {
var out = [], i, len;
if (out[i] instanceof Array === false){
return arr;
}
for (i = 0, len = arr.length; i < len; i++) {
if (out[i] instanceof Array){
out[i] = deepcopy(arr[i]);
} else {
out[i] = arr[i];
}
};
return a;
}
//测试
var arr1 = [1, 2, 3, 4],
arr2 = array_copy(arr1);
console.log(arr1, arr2);
arr2[2] = 10;
console.log(arr1[2], arr2[2]);
function array_copy(arr) {
var out = [], i, len;
if (out[i] instanceof Array === false){
return arr;
}
for (i = 0, len = arr.length; i < len; i++) {
if (out[i] instanceof Array){
out[i] = deepcopy(arr[i]);
} else {
out[i] = arr[i];
}
};
return a;
}
//测试
var arr1 = [1, 2, 3, 4],
arr2 = array_copy(arr1);
console.log(arr1, arr2);
arr2[2] = 10;
console.log(arr1[2], arr2[2]);

1.2 变通的复制实现

经常出现在面试题中的取巧方法,是使用 slice 或 contcat 方法实现。示例:

JavaScript

var arr1 = [1, 2, 3, 4],
arr2 = arr1.slice(0),
arr3 = arr1.concat();
console.log(arr1, arr2, arr3);
arr2[2] = 10;
arr3[2] = 11;
console.log(arr1[2], arr2[2], arr3[2]);
var arr1 = [1, 2, 3, 4],
arr2 = arr1.slice(0),
arr3 = arr1.concat();
console.log(arr1, arr2, arr3);
arr2[2] = 10;
arr3[2] = 11;
console.log(arr1[2], arr2[2], arr3[2]);

2. 数组的深度复制

普通的一维数组且值为非引用类型,使用上述方法是没有问题的,否则就比较麻烦了。深度复制需要考虑数组值为各种引用类型的情况。

2.1 使用 JSON 方法

JSON.stringify(array) 然后再 JSON.parse()。示例:

JavaScript

var arr1 = [1, 2, [3, 4], {a: 5, b: 6}, 7],
arr2 = JSON.parse(JSON.stringify(arr1));
console.log(arr1, arr2);
arr2[1] = 10;
arr2[3].a = 20;
console.log(arr1[1], arr2[1]);
console.log(arr1[3], arr2[3]);
var arr1 = [1, 2, [3, 4], {a: 5, b: 6}, 7],
arr2 = JSON.parse(JSON.stringify(arr1));
console.log(arr1, arr2);
arr2[1] = 10;
arr2[3].a = 20;
console.log(arr1[1], arr2[1]);
console.log(arr1[3], arr2[3]);

此方法存在对古老浏览器的兼容性问题。如确需要作兼容,可引入如下兼容文件解决:

https://github.com/douglascrockford/JSON-js/blob/master/json2.js

注意:如果数组值为函数,上述方法还是不行的。

2.2 深度复制的完全实现

考虑到多维数组的嵌套,以及数组值为对象的情况,可以作如下原型扩展(当然写为普通函数实现也是可以的,原型扩展是不建议的方式):

JavaScript

Object.prototype.clone = function () {
var o = {};
for (var i in this) {
o[i] = this[i];
}
return o;
};
Array.prototype.clone = function () {
var arr = [];
for (var i = 0; i < this.length; i++)
if (typeof this[i] !== 'object') {
arr.push(this[i]);
} else {
arr.push(this[i].clone());
}
return arr;
};
//测试1 Object
var obj1 = {
name: 'Rattz',
age: 20,
hello: function () {
return "I'm " + name;
}
};
var obj2 = obj1.clone();
obj2.age++;
console.log(obj1.age);
//测试2 Array
var fun = function(log) {console.log},
arr1 = [1, 2, [3, 4], {a: 5, b: 6}, fun],
arr2 = arr1.clone();
console.log(arr1, arr2);
arr2[2][1]= 'Mike';
arr2[3].a = 50;
arr2[4] = 10;
console.log(arr1, arr2);
Object.prototype.clone = function () {
var o = {};
for (var i in this) {
o[i] = this[i];
}
return o;
Array.prototype.clone = function () {
var arr = [];
for (var i = 0; i < this.length; i++)
if (typeof this[i] !== 'object') {
arr.push(this[i]);
} else {
arr.push(this[i].clone());
}
return arr;
//测试1 Object
var obj1 = {
name: 'Rattz',
age: 20,
hello: function () {
return "I'm " + name;
}
var obj2 = obj1.clone();
console.log(obj1.age);
//测试2 Array
var fun = function(log) {console.log},
arr1 = [1, 2, [3, 4], {a: 5, b: 6}, fun],
arr2 = arr1.clone();
console.log(arr1, arr2);
arr2[2][1]= 'Mike';
arr2[3].a = 50;
arr2[4] = 10;
console.log(arr1, arr2);

2.3 使用 jQuery 的 extend 方法

如果你在使用 jQuery,那么最简单的方法是使用 extend 插件方法。示例:

JavaScript

var arr1 = [1, 2, [3, 4], {a: 5, b: 6}, 7],
arr2 = $.extend(true, [], arr1);
console.log(arr1, arr2);
arr2[1] = 10;
console.log(arr1, arr2);
var arr1 = [1, 2, [3, 4], {a: 5, b: 6}, 7],
arr2 = $.extend(true, [], arr1);
console.log(arr1, arr2);
arr2[1] = 10;
console.log(arr1, arr2);

以上所述是小编给大家介绍的JavaScript 数组的深度复制解析,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
Firefox/Chrome/Safari的中可直接使用$/$$函数进行调试
Feb 13 Javascript
onclick与listeners的执行先后问题详细解剖
Jan 07 Javascript
Js-$.extend扩展方法使方法参数更灵活
Jan 15 Javascript
jquery 按钮状态效果 正常、移上、按下
Aug 12 Javascript
防止登录页面出现在frame中js代码
Jul 22 Javascript
Javascript学习笔记之函数篇(五) : 构造函数
Nov 23 Javascript
Javascript 运动中Offset的bug解决方案
Dec 24 Javascript
JavaScript数组常用方法
Mar 02 Javascript
bootstrap switch开关组件使用方法详解
Aug 22 Javascript
vue通过video.js解决m3u8视频播放格式的方法
Jul 30 Javascript
JavaScript实现世界各地时间显示
Sep 07 Javascript
vue 通过 Prop 向子组件传递数据的实现方法
Oct 30 Javascript
AngularJS实现与Java Web服务器交互操作示例【附demo源码下载】
Nov 02 #Javascript
Centos7 中 Node.js安装简单方法
Nov 02 #Javascript
AngularJS入门教程之与服务器(Ajax)交互操作示例【附完整demo源码下载】
Nov 02 #Javascript
用AngularJS来实现监察表单按钮的禁用效果
Nov 02 #Javascript
AngularJS入门教程之Cookies读写操作示例
Nov 02 #Javascript
js导出excel文件的简洁方法(推荐)
Nov 02 #Javascript
AngularJS入门教程之多视图切换用法示例
Nov 02 #Javascript
You might like
无法在发生错误时创建会话,请检查 PHP 或网站服务器日志,并正确配置 PHP 安装最快的解决办法
2010/08/01 PHP
php UBB 解析实现代码
2011/11/27 PHP
支持中文的php加密解密类代码
2011/11/27 PHP
php实现文件上传及头像预览功能
2017/01/15 PHP
使用ucenter实现多站点同步登录的讲解
2019/03/21 PHP
解决PhpStorm64不能启动的问题
2020/06/20 PHP
Mootools 1.2教程 选项卡效果(Tabs)
2009/09/15 Javascript
javascript setTimeout和setInterval 的区别
2009/12/08 Javascript
jQuery each()小议
2010/03/18 Javascript
jquery ajax提交整个表单元素的快捷办法
2013/03/27 Javascript
JavaScript控制图片加载完成后调用回调函数的方法
2015/03/20 Javascript
浅谈Sizzle的“编译原理”
2015/04/14 Javascript
JavaScript中操作字符串小结
2015/05/04 Javascript
jQuery Ajax 实例代码 ($.ajax、$.post、$.get)
2016/04/29 Javascript
js实现放大镜特效
2017/05/18 Javascript
jQuery实现的淡入淡出图片轮播效果示例
2018/08/29 jQuery
解决Vue+Element ui开发中碰到的IE问题
2018/09/03 Javascript
发布Angular应用至生产环境的方法
2018/12/10 Javascript
node.js实现http服务器与浏览器之间的内容缓存操作示例
2020/02/11 Javascript
js回到页面指定位置的三种方式
2020/12/17 Javascript
详解python 模拟豆瓣登录(豆瓣6.0)
2019/04/18 Python
python中的RSA加密与解密实例解析
2019/11/18 Python
浅谈pandas.cut与pandas.qcut的使用方法及区别
2020/03/03 Python
python单元测试框架pytest的使用示例
2020/10/07 Python
使用python画出逻辑斯蒂映射(logistic map)中的分叉图案例
2020/12/11 Python
详解python第三方库的安装、PyInstaller库、random库
2021/03/03 Python
CSS3的常见transformation图形变化用法小结
2016/05/13 HTML / CSS
Canvas环形饼图与手势控制的实现代码
2019/11/08 HTML / CSS
总经理岗位职责
2013/11/09 职场文书
应聘收银员个人的求职信
2013/11/30 职场文书
施工工地安全标语
2014/06/07 职场文书
销售2014年度工作总结
2014/12/08 职场文书
爱心捐款活动总结
2015/05/09 职场文书
市语委办2016年第十九届“推普周”活动总结
2016/04/05 职场文书
MySQL通过binlog恢复数据
2021/05/27 MySQL
oracle删除超过N天数据脚本的方法
2022/02/28 Oracle