JavaScript中浅拷贝与深拷贝的原理及实现方法
本文详细解析JavaScript中的浅拷贝与深拷贝机制。通过数组slice、concat方法及对象属性遍历,演示如何实现数据备份而不影响原值。同时介绍jQuery.extend的深拷贝实现,帮助开发者理解引用类型与基本类型的复制差异,避免数据修改时的意外关联。
JavaScript浅拷贝与深拷贝概述
本文将深入探讨JavaScript中面向对象的深拷贝与浅拷贝概念,内容具有实用参考价值。
浅拷贝的核心在于仅复制引用地址。此时,所有指向该数据的变量共享同一份数据源,对任一变量的修改都会反映在其它变量上。
深拷贝则涉及更复杂的逻辑:它复制变量值,针对非基本类型(如对象或数组),会递归遍历至基本类型变量,随后逐一复制其值。
为辅助理解,此处配有一张示意图展示拷贝过程。

数组的深浅拷贝实现
一、数组的深浅拷贝
在JavaScript操作中,常需对数组进行备份。若仅通过直接赋值给新变量,修改新数组中的任意元素,原数组也会随之改变,这往往引发非预期的程序错误。
var arr = ["One","Two","Three"];
var arrto = arr;
arrto[1] = "test";
document.writeln("数组的原始值:" + arr + "<br />");//Export:数组的原始值:One,test,Three
document.writeln("数组的新值:" + arrto + "<br />");//Export:数组的新值:One,test,Three
上述直接赋值属于浅拷贝。通常我们需要的是保持原数组arr的值不变,而得到一份独立的新数据,这正是深拷贝的目标。
方法一:利用js的slice函数
var arr = ["One","Two","Three"];
var arrtoo = arr.slice(0);
arrtoo[1] = "set Map";
document.writeln("数组的原始值:" + arr + "<br />");//Export:数组的原始值:One,Two,Three
document.writeln("数组的新值:" + arrtoo + "<br />");//Export:数组的新值:One,set Map,Three
方法二:利用js的concat方法
var arr = ["One","Two","Three"];
var arrtooo = arr.concat();
arrtooo[1] = "set Map To";
document.writeln("数组的原始值:" + arr + "<br />");//Export:数组的原始值:One,Two,Three
document.writeln("数组的新值:" + arrtooo + "<br />");//Export:数组的新值:One,set Map To,Three
对象的深浅拷贝与jQuery示例
二、对象的深浅拷贝
var a={name:'yy',age:26};
var b=new Object();
b.name=a.name;
b.age=a.age;
a.name='xx';
console.log(b);//Object { name="yy", age=26}
console.log(a);//Object { name="xx", age=26}
对象深拷贝的基本思路是遍历原对象的所有属性,并将这些属性值赋给一个新对象。
var deepCopy= function(source) {
var result={};
for (var key in source) {
result[key] = typeof source[key]==='object'? deepCoyp(source[key]): source[key];
}
return result;
}
以下以jQuery中的一个示例进行说明。
jQuery.extend = jQuery.fn.extend = function() {//1.将extend方法扩展到JQ(函数)下边:扩展静态方法
//2. jQuery.fn.extend 把extend扩展到jq.fn下 且jQuery.fn = jQuery.prototype 扩展实例方法
// 1.2.功能相似
var options, name, src, copy, copyIsArray, clone, //定义一些变量
target = arguments[0] || {},
//目标元素是【0】第一个元素$.extend( a , { name : 'hello' } , { age : 30 } );
i = 1, //第一个元素的位置
length = arguments.length,//第一个个对象的元素
deep = false; //是否是深拷贝 默认 false不是
// Handle a deep copy situation 看是不是深拷贝情况
if ( typeof target === "boolean" ) { //是布尔值
deep = target;
target = arguments[1] || {}; //目标元素是第二个$.extend( true , a , b )
// skip the boolean and the target
i = 2;
}
// Handle case when target is a string or something (possible in deep copy) 看参数正确不
if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
// 当目标不是对象或者不是函数的时候
target = {}; //变成一个空的jason
}
// extend jQuery itself if only one argument is passed看是不是插件情况
if ( length === i ) { //只写了一个对象 要把这个对象扩展到jq源码上 静态方法 或者是实例方法
target = this; //this 是$ 或者 $();
--i;
}
// 可能有多个对象情况
for ( ; i < length; i++ ) {
// Only deal with non-null/undefined values
if ( (options = arguments[ i ]) != null ) {//看后边的对象是否都有值
// Extend the base object
for ( name in options ) {
src = target[ name ];
copy = options[ name ];
// Prevent never-ending loop
if ( target === copy ) {//防止循环引用
continue;//跳出本次循环继续执行
// $.extend( a , { name : a } ) );循环引用 a也是一个对象
}
// Recurse if we're merging plain objects or arrays深拷贝
if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
// 是深拷贝 且需有var b = { name : { age : 30 } }; 且b必须是对象自变量(jason) 或者是个数组
//递归
if ( copyIsArray ) { //数组
copyIsArray = false;
clone = src && jQuery.isArray(src) ? src : []; //定义一个空数组
} else {//jason
clone = src && jQuery.isPlainObject(src) ? src : {};//看原有的属性有没有且是不是jason定义一个空jason
}
// var a = { name : { job : 'it' } }; 看有没有原有的属性 有的话在原有的上边添加
// var b = { name : {age : 30} };
// $.extend( true , a , b );//a继承b
// console.log( a ); a{ name:{ job : 'it' ,age : 30}} 如果只有一个{} 则只有,age : 30
// Never move original objects, clone(a) them
target[ name ] = jQuery.extend( deep, clone, copy );
//调用函数本身进行进一步的递归处理
// Don't bring in undefined values浅拷贝
} else if ( copy !== undefined ) {
target[ name ] = copy; //直接复制因为里边没有对象
}
}
}
}
// Return the modified object
return target;
};
以上内容为本文的全部总结,希望能为读者的学习提供有益帮助,欢迎继续支持本站获取更多技术分享。
JS split切割后出现空字符串怎么过滤
2026-11-05 16:00:30
在 React 或 Vue 项目中封装使用 JS 节流防抖
2026-11-05 15:27:29
JavaScript中怎么将带小数的字符串转为整数?
2026-11-05 14:32:38
怎么用JavaScript策略模式重构电商促销计算逻辑?
2026-11-05 14:01:09
JS使用constructor判断数据类型可靠吗
2026-11-05 13:49:41
