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 相关文章推荐
javascritp实现input输入框相关限制用法
Jun 29 Javascript
JS event使用方法详解
Apr 28 Javascript
实例详解JSON数据格式及json格式数据域字符串相互转换
Jan 07 Javascript
js Canvas实现圆形时钟教程
Sep 19 Javascript
js的三种继承方式详解
Jan 21 Javascript
Webpack常见静态资源处理-模块加载器(Loaders)+ExtractTextPlugin插件
Jun 29 Javascript
让网站自动生成章节目录索引的多个js代码
Jan 07 Javascript
vue--点击当前增加class,其他删除class的方法
Sep 15 Javascript
vue+axios 前端实现登录拦截的两种方式(路由拦截、http拦截)
Oct 24 Javascript
react+ant design实现Table的增、删、改的示例代码
Dec 27 Javascript
react中使用css的7中方式(最全总结)
Feb 11 Javascript
jQuery使用jsonp实现百度搜索的示例代码
Jul 08 jQuery
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命令行脚本接收传入参数的三种方式
2014/08/20 PHP
javascript parseInt与Number函数的区别
2010/01/21 Javascript
JQuery操作iframe父页面与子页面的元素与方法(实例讲解)
2013/11/20 Javascript
javascript判断网页是关闭还是刷新
2015/09/12 Javascript
Backbone.js框架中Model与Collection的使用实例
2016/05/07 Javascript
Svg.js实例教程及使用手册详解(一)
2016/05/16 Javascript
bootstrap实现的自适应页面简单应用示例
2017/03/09 Javascript
关于Promise 异步编程的实例讲解
2017/09/01 Javascript
加载 vue 远程代码的组件实例详解
2017/11/20 Javascript
Javascript防止图片拉伸的自适应处理方法
2017/12/26 Javascript
你可能不知道的前端算法之文字避让(inMap)
2018/01/12 Javascript
vue超时计算的组件实例代码
2018/07/09 Javascript
微信 jssdk 签名错误invalid signature的解决方法
2019/01/14 Javascript
Vue.js项目实战之多语种网站的功能实现(租车)
2019/08/07 Javascript
layer弹出层取消遮罩的方法
2019/09/25 Javascript
Vue.js watch监视属性知识点总结
2019/11/11 Javascript
python使用xauth方式登录饭否网然后发消息
2014/04/11 Python
对Python 文件夹遍历和文件查找的实例讲解
2018/04/26 Python
python 含子图的gif生成时内存溢出的方法
2019/07/07 Python
详解python中的生成器、迭代器、闭包、装饰器
2019/08/22 Python
Django实现简单网页弹出警告代码
2019/11/15 Python
Html5页面中的返回实现的方法
2018/02/26 HTML / CSS
关于webview适配H5上传照片或者视频文件的方法
2020/11/04 HTML / CSS
澳大利亚百货商店中销量第一的商务衬衫品牌:Van Heusen
2018/07/26 全球购物
Omio俄罗斯:一次搜索公共汽车、火车和飞机的机票
2018/11/17 全球购物
南京软件公司的.net程序员笔试题
2014/08/31 面试题
问卷调查计划书
2014/01/10 职场文书
销售人员自我评价
2014/02/01 职场文书
2014年安全生产目标责任书
2014/07/23 职场文书
2014党支部对照检查材料思想汇报
2014/10/05 职场文书
物业项目经理岗位职责
2015/04/01 职场文书
2015年企业员工工作总结范文
2015/05/21 职场文书
员工担保书范本
2015/09/22 职场文书
2016中秋节广告语
2016/01/28 职场文书
MySql子查询IN的执行和优化的实现
2021/08/02 MySQL
MySQL脏读,幻读和不可重复读
2022/05/11 MySQL