js变量浅拷贝 深拷贝
js的变量分为简单数据类型和复杂数据类型(即引用类型)。
简单数据类型在内存中占据着固定大小的空间,被保存在栈内存中,在简单数据类型中,当一个变量指向另一个变量时,只是创建了值的副本,两个变量只是占用的空间大小相同,值相同,但是存储的位置不同。因此,当其中一个值改变的时候,不会对另一个值有影响。
对于引用类型,值是对象,保存在堆内存中。当一个变量指向另一个变量时,它们其实指向的是同一个内存空间,变量保存的是指向实际对象的指针。从一个变量向另一个变量复制引用类型的值,复制的其实是指针地址而已,因此两个变量最终都指向同一个对象。
引用类型:
var obj1={name:'sally'};
var obj2=obj1;
obj2.age=9;
console.log(obj1)
//{name: "sally", age: 9}
console.log(obj2)
{name: "sally", age: 9}
obj赋值给obj2后,改变其中一个对象的属性值,两个对象都发生了改变,根本原因就是obj和obj2两个变量都指向同一个指针,赋值时只是复制了指针地址,它们指向同一个引用。
1、浅拷贝
以上就是简单的浅拷贝的例子,但是改变任一变量都会互相影响。
2、深拷贝
深拷贝就是完全复制变量的一份给其他的变量备份。解决浅拷贝带来的问题;
1、数组
(1)只包含简单数据类型的数组
对于仅仅包含简单数据类型的数组来说可以使用slice和concat来实现;
如:
var a = b.slice(0);
var b = [].concat(b);//或者b.concat();
- arrayObj.slice(start, [end]) 该方法返回一个 Array 对象,其中包含了 arrayObj 的指定部分。不会改变原数组
- arrayObj.concat() 方法用于连接两个或多个数组。该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本。
(2)数组元素中存在数组(复杂类型)
如:
var a=[1,3,4,[46,23]];
var b = a.slice(0);
b[3][0]='34';
console.log(a,b)
//a、b均为[1,3,4,[34,23]
可见,当改变b[3].name的时候,a也会被改变。解决次问题可以定义以下函数:
function deepCopyArray(arr){
var output = arr.slice(0);
for(var index=0;index<output.length;index++){
if(Object.prototype.toString.call(output[index])==='[object Array]'){
output[index]=copyArray(output[index]);
}
}
return output;
}
2、对象
对象的深拷贝实现原理: 定义一个新的对象,遍历源对象的属性 并 赋给新对象的属性
如:
var a={name:'sally',age:26};
var b={};
b.name = a.name;
b.age = a.age;
b.hobby = 'sing'
console.log(a); //{name: "sally", age: 26}
console.log(b); //{name: "sally", age: 26, hobby: "sing"}
如果对象中属性值仅仅是简单数据类型,遍历源对象的属性,将对应的属性值赋给最后的对象即可,如果源对象中的属性值是对象的话就需要通过递归来实现了。
如下实现的对象深拷贝函数:
function deepCopyObject(source){
var result = {};
for(var key in source) {
if(typeof source[key] === 'object') {
result[key] = deepCopy(source[key]) //如果属性值为对象,递归
} else {
result[key] = source[key]
}
}
return result;
}
3、数组对象混合的通用深拷贝函数
function deepCopy(input){
var output;
if(Object.prototype.toString.call(input)==='[object Array]'){
output = input.slice(0);
}
if(Object.prototype.toString.call(input)==='[object Object]'){
output = {};
for(let key in input) {
output[key] = input[key]
}
}
for(let key in output){
if(typeof output[key]==='object'){
output[key]=deep(output[key]);
}
}
return output;
}
验证代码
(1)数组包含数组元素
var a=[1,3,4,[46,23]];
var b = deep(a);
b[3][0]=34;
console.log(a,b)
(2)数组包含数组和对象
var a=[1,3,4,[46,23],{name:'sally'}];
var b = deep(a);
b[3][0]=34;
b[4].name='bob';
console.log(a,b)
(3)对象包含对象
var a={name:'sally',list:{num:[1,2,3,4]}};
var b = deep(a);
b.list.num[2]=34;
b.name='bob';
console.log(a,b)
(4)对象包含数组
var a={name:'sally',list:[1,2,3,4]};
var b = deep(a);
b.list[0]=34;
b.name='bob';
console.log(a,b)
js变量浅拷贝 深拷贝的更多相关文章
- js库 - 浅拷贝 & 深拷贝
学了堆栈内存空间,应该就理解了什么叫简单数据类型存在栈内存,复杂数据类型存在堆内存了. 然后面试中经常会问.业务中也经常会遇到的问题就是深浅拷贝的问题了. 栈内存中简单数据类型直接拷贝就能得到一个副本 ...
- JS中有关对象的继承以及实例化、浅拷贝深拷贝的奥秘
一.属性的归属问题 JS对象中定义的属性和方法如果不是挂在原型链上的方法和属性(直接通过如类似x的方式进行定义)都只是在该对象上,对原型链上的没有影响.对于所有实例共用的方法可直接定义在原型链上这样实 ...
- Javascript/js 的浅拷贝与深拷贝(复制)学习随笔
js变量的数据类型值分基本类型值和引用类型值. 在ES6(ECMAScript6)以前,基本数据类型包括String.Number.Boolean.Undefined.Null. 基本类型值的复制(拷 ...
- js中浅拷贝和深拷贝以及深拷贝的实现
前言:2019年的第一篇分享... 一.什么是基本类型值和引用类型值?ECMAScript包括两个不同类型的值:基本数据类型和引用数据类型.基本数据类型指的是简单的数据段,引用数据类型指的是有多个值构 ...
- JS对象复制(深拷贝、浅拷贝)
如何在 JS 中复制对象 在本文中,我们将从浅拷贝(shallow copy)和深拷贝(deep copy)两个方面,介绍多种 JS 中复制对象的方法. 在开始之前,有一些基础知识值得一提:Javas ...
- js对象浅拷贝和深拷贝详解
js对象浅拷贝和深拷贝详解 作者:i10630226 字体:[增加 减小] 类型:转载 时间:2016-09-05我要评论 这篇文章主要为大家详细介绍了JavaScript对象的浅拷贝和深拷贝代码,具 ...
- js 对象浅拷贝和深拷贝
var model={name:"boy",age:13}; var CopyModel=model; console.log(CopyModel.name); model.nam ...
- 浅拷贝 &&&深拷贝 实现
1.浅拷贝 //1.直接赋值给一个变量 //浅拷贝 //2.Object.assign() //浅拷贝 let obj4={} let obj5={money:50000} obj4.__proto_ ...
- $.extend()浅拷贝深拷贝
参考网址:http://bijian1013.iteye.com/blog/2255037 jQuery.extend() 函数用于将一个或多个对象的内容合并到目标对象. 注意:1. 如果只为$.ex ...
随机推荐
- 安装wls报(主清单位置 "/u01/app/oracle/inventory" 无效 (无法读取/写入/执行))
安装出现的错误: [weblogic@localhost ~]$ java -jar fmw_12.1.3.0.0_wls.jar 启动程序日志文件为/tmp/OraInstall2019-07-31 ...
- linux系统及命令学习
1,基本概念 Shell(命令行):是一个程序,接受键盘输入的命令,并将命令传递给操作系统进行执行. Bash:Bourne Again Shell, 是大多数linux系统分之中所带的一种shell ...
- 机器学习之Xgboost算法
知识点 """ xgboost:是一种提升算法,串行的决策树 过程: 第一棵树:目标值:1000 ,预测值:950 第二颗树:目标值:1000-950=50(残差作为输入 ...
- GWO(灰狼优化)算法MATLAB源码逐行中文注解(转载)
以优化SVM算法的参数c和g为例,对GWO算法MATLAB源码进行了逐行中文注解. tic % 计时器 %% 清空环境变量 close all clear clc format compact %% ...
- spring boot系列(六)spring boot 配置mybatis(xml简化版)
orm框架的本质是简化编程中操作数据库的编码,发展到现在基本上就剩两家了,一个是宣称可以不用写一句SQL的hibernate,一个是可以灵活调试动态sql的mybatis,两者各有特点,在企业级系统开 ...
- Paper Mark
BigCowPeking的CSDN博客 https://blog.csdn.net/wfei101/article/category/7120809 Low Rank Structure of Lea ...
- docker search 报错
docker 出现 Error response from daemon vim /etc/containers/registries.conf [registries.search]registri ...
- C/C++中结构体总结笔记
结构体的定义方式 在C/C++中结构体的定义方式有很多种,做个简单的总结. 定义方式1: struct st{ int a; }; 定义方式2: struct _st{ int a; } st; 定义 ...
- Java之属性和普通方法
一.定义类 上一节讲了很多深奥的理论,那么这节我们就得实践一下,先简单描述一下我们的实体世界:有一个学生小明,那么这个学生就是一个对象,这个对象有哪些属性和方法呢,我们可以先简单抽象一下,属性有(姓名 ...
- 解读GitHub EntityComponentSystemSamples
出自Unity官方的ECS项目示例,该项目的第一次Commit是在2018年3月20号,距离现在一年半的时间,这期间ECS本身的生态在快速发展,稳定性也是逐步提升,期待在2020年的Unity版本中作 ...