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 相关文章推荐
Javascript 陷阱 window全局对象
Nov 26 Javascript
一个JQuery操作Table的代码分享
Mar 30 Javascript
jQuery 联动日历实现代码
May 31 Javascript
一个封装js代码-----展开收起效果示例
Jul 03 Javascript
JavaScript中apply方法的应用技巧小结
Sep 29 Javascript
bootstrap中添加额外的图标实例代码
Feb 15 Javascript
微信小程序自定义toast实现方法详解【附demo源码下载】
Nov 28 Javascript
JavaScript实现二叉树定义、遍历及查找的方法详解
Dec 20 Javascript
JS实现百度搜索接口及链接功能实例代码
Feb 02 Javascript
vue.extend实现alert模态框弹窗组件
Apr 28 Javascript
Vue中跨域及打包部署到nginx跨域设置方法
Aug 26 Javascript
JS前端轻量fabric.js系列之画布初始化
Aug 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 Mysql日期和时间函数集合
2007/11/16 PHP
php中用foreach来操作数组的代码
2011/07/17 PHP
javascript 控制 html元素 显示/隐藏实现代码
2009/09/01 Javascript
jQuery 判断元素上是否绑定了事件
2009/10/28 Javascript
IE6 弹出Iframe层中的文本框“经常”无法获得输入焦点
2009/12/27 Javascript
解决Extjs4中form表单提交后无法进入success函数问题
2013/11/26 Javascript
jquery实现图片翻页效果
2013/12/23 Javascript
jQuery 设置 CSS 属性示例介绍
2014/01/16 Javascript
require简单实现单页应用程序(SPA)
2016/07/12 Javascript
详解使用grunt完成requirejs的合并压缩和js文件的版本控制
2017/03/02 Javascript
JavaScript手风琴页面制作
2017/05/17 Javascript
JavaScript实现跟随滚动缓冲运动广告框
2017/07/15 Javascript
JS删除数组里的某个元素方法
2018/02/03 Javascript
javascriptvoid(0)含义以及与&quot;#&quot;的区别讲解
2019/01/19 Javascript
vue-cli脚手架打包静态资源请求出错的原因与解决
2019/06/06 Javascript
layui table去掉右侧滑动条的实现方法
2019/09/05 Javascript
vue实现在线学生录入系统
2020/05/30 Javascript
微信小程序实现多图上传
2020/06/19 Javascript
vue实现简单加法计算器
2020/10/22 Javascript
[48:44]2014 DOTA2国际邀请赛中国区预选赛5.21 TongFu VS HGT
2014/05/22 DOTA
[50:50]完美世界DOTA2联赛PWL S3 INK ICE vs DLG 第一场 12.20
2020/12/23 DOTA
Python functools模块学习总结
2015/05/09 Python
python ChainMap的使用和说明详解
2019/06/11 Python
python绘制无向图度分布曲线示例
2019/11/22 Python
Python搭建HTTP服务过程图解
2019/12/14 Python
python环境搭建和pycharm的安装配置及汉化详细教程(零基础小白版)
2020/08/19 Python
三星印度官网:Samsung印度
2019/08/03 全球购物
介绍一下Transact-SQL中SPACE函数的用法
2015/09/01 面试题
单位介绍信范文
2014/01/18 职场文书
个人担保书格式范文
2014/05/12 职场文书
日语专业求职信
2014/07/04 职场文书
爱牙日活动总结
2014/08/29 职场文书
公司人事管理制度
2015/08/05 职场文书
礼貌问候语大全
2015/11/10 职场文书
mysql 带多个条件的查询方式
2021/06/05 MySQL
Golang中channel的原理解读(推荐)
2021/10/16 Golang