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.opener的用法分析
Apr 07 Javascript
jQuery拖拽 &amp; 弹出层 介绍与示例
Dec 27 Javascript
特殊情况下如何获取span里面的值
May 20 Javascript
JavaScript日期类型的一些用法介绍
Mar 02 Javascript
轻量级jQuery插件slideBox实现带底栏轮播(焦点图)代码
Mar 28 Javascript
对比分析Django的Q查询及AngularJS的Datatables分页插件
Feb 07 Javascript
javascript 显示全局变量与隐式全局变量的区别
Feb 09 Javascript
JS实现的简单表单验证功能完整实例
Oct 14 Javascript
实例学习JavaScript读取和写入cookie
Jan 29 Javascript
vue指令v-html使用过滤器filters功能实例
Oct 25 Javascript
Vue父组件监听子组件生命周期
Sep 03 Javascript
js轮播图之旋转木马效果
Oct 13 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
如何给phpadmin一个保护
2006/10/09 PHP
从一个不错的留言本弄的mysql数据库操作类
2007/09/02 PHP
深入php socket的讲解与实例分析
2013/06/13 PHP
php中有关合并某一字段键值相同的数组合并的改进
2015/03/10 PHP
php通过文件流方式复制文件的方法
2015/03/13 PHP
解决ThinkPHP关闭调试模式时报错的问题汇总
2015/04/22 PHP
php如何获取文件的扩展名
2015/10/28 PHP
PHP 7.0.2 正式版发布
2016/01/08 PHP
javascript中的107个基础知识收集整理 推荐
2010/03/29 Javascript
js动画(animate)简单引擎代码示例
2012/12/04 Javascript
jQuery实现预加载图片的方法
2015/03/17 Javascript
手机开发必备技巧:javascript及CSS功能代码分享
2015/05/25 Javascript
javascript实现根据时间段显示问候语的方法
2015/06/18 Javascript
轻量级网页遮罩层jQuery插件用法实例
2015/07/31 Javascript
基于JavaScript Array数组方法(新手必看篇)
2016/08/20 Javascript
canvas绘制多边形
2017/02/24 Javascript
微信小程序 ecshop地址三级联动实现实例代码
2017/02/28 Javascript
使用jQuery监听扫码枪输入并禁止手动输入的实现方法(推荐)
2017/03/21 jQuery
JS中把函数作为另一函数的参数传递方法(总结)
2017/06/28 Javascript
微信小程序组件之srcoll-view的详解
2017/10/19 Javascript
JavaScript实现的简单Tab点击切换功能示例
2018/07/06 Javascript
在elementui中Notification组件添加点击事件实例
2020/11/11 Javascript
python编写微信远程控制电脑的程序
2018/01/05 Python
对Python中range()函数和list的比较
2018/04/19 Python
Flask项目中实现短信验证码和邮箱验证码功能
2019/12/05 Python
Pygame的程序开始示例代码
2020/05/07 Python
详解HTML5中download属性的应用
2015/08/06 HTML / CSS
HTML5+CSS3:3D展示商品信息示例
2017/01/03 HTML / CSS
Omio法国:全欧洲低价大巴、火车和航班搜索和比价
2017/11/13 全球购物
学校司机岗位职责
2013/11/14 职场文书
人事文员岗位职责
2014/02/16 职场文书
慰问信格式规范
2015/03/23 职场文书
幼儿园大班教学反思
2016/03/02 职场文书
详解如何使用Nginx解决跨域问题
2022/05/06 Servers
Nginx 常用配置
2022/05/15 Servers
Apache POI操作批量导入MySQL数据库
2022/06/21 Servers