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 相关文章推荐
jquery ui resizable bug解决方法
Oct 26 Javascript
JavaScript 注册事件代码
Jan 27 Javascript
利用jQuery操作对象数组的实现代码
Apr 27 Javascript
document.documentElement的一些使用技巧
Apr 18 Javascript
『jQuery』.html(),.text()和.val()的概述及使用
Apr 22 Javascript
jQuery html()方法使用不了无法显示内容的问题
Aug 06 Javascript
面向切面编程(AOP)的理解
May 01 Javascript
jQuery基于ajax实现带动画效果无刷新柱状图投票代码
Aug 10 Javascript
通过js获取上传的图片信息(临时保存路径,名称,大小)然后通过ajax传递给后端的方法
Oct 01 Javascript
Google 地图控件集详解及实例代码
Aug 06 Javascript
jQuery easyui刷新当前tabs的方法
Sep 23 Javascript
JavaScript TAB栏切换效果的示例
Nov 05 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取整数函数常用的四种方法小结
2012/07/05 PHP
php中生成随机密码的自定义函数代码
2013/10/21 PHP
php中的静态变量的基本用法
2014/03/20 PHP
PHP绕过open_basedir限制操作文件的方法
2018/06/10 PHP
如何在PHP中使用数组
2020/06/09 PHP
JS中confirm,alert,prompt函数使用区别分析
2010/04/01 Javascript
jQuery队列控制方法详解queue()/dequeue()/clearQueue()
2010/12/02 Javascript
jQuery 开发者应该注意的9个错误
2012/05/03 Javascript
鼠标事件的screenY,pageY,clientY,layerY,offsetY属性详解
2015/03/12 Javascript
NodeJs中的VM模块详解
2015/05/06 NodeJs
js实现键盘Enter键提交表单的方法
2015/05/27 Javascript
使用AngularJS处理单选框和复选框的简单方法
2015/06/19 Javascript
基于JavaScript实现弹出框效果
2016/02/19 Javascript
jQuery中的siblings()是什么意思(推荐)
2016/12/29 Javascript
利用Jasmine对Angular进行单元测试的方法详解
2017/06/12 Javascript
js字符限制(字符截取) 一个中文汉字算两个字符
2017/09/12 Javascript
js实现鼠标移动到图片产生遮罩效果
2017/10/21 Javascript
详解create-react-app 自定义 eslint 配置
2018/06/07 Javascript
解决JavaScript layui 下拉框不显示的问题
2018/08/14 Javascript
vue新vue-cli3环境配置和模拟json数据的实例
2018/09/19 Javascript
CentOS7中源码编译安装NodeJS的完整步骤
2018/10/13 NodeJs
Vue使用Proxy监听所有接口状态的方法实现
2019/06/07 Javascript
利用d3.js制作连线动画图与编辑器的方法实例
2019/09/05 Javascript
Python中请使用isinstance()判断变量类型
2014/08/25 Python
Python实现windows下模拟按键和鼠标点击的方法
2015/03/13 Python
详解Python中的循环语句的用法
2015/04/09 Python
python机器学习之随机森林(七)
2018/03/26 Python
Django配置celery(非djcelery)执行异步任务和定时任务
2018/07/16 Python
Python使用post及get方式提交数据的实例
2019/01/24 Python
基于tensorflow for循环 while循环案例
2020/06/30 Python
python学习之使用Matplotlib画实时的动态折线图的示例代码
2021/02/25 Python
GANT英国官方网上商店:甘特衬衫
2018/02/06 全球购物
公司证明怎么写
2014/09/22 职场文书
单位接收函范文
2015/01/30 职场文书
挂职锻炼工作总结2015
2015/05/28 职场文书
解决Django transaction进行事务管理踩过的坑
2021/04/24 Python