JS 深浅拷贝的区别以及实现方式
在学习JS时最让我头疼的就是栈和堆以及一切概念性的问题 也是最近才把想给这个搞通提上了日程
简单来说 深浅拷贝的区别:
A复制了B 当改变 A 中的一个元素 B 中的这个元素也改变了 这就叫做浅拷贝
反之 改变 A 中的元素 B 中的元素并没有一起改变 这就叫做 深拷贝 深拷贝都是针对于较为复杂的object类型
这个也就要牵扯到栈和堆 以及 数据类型的概念了
JS几大基本数据类型: Null Undefined Number Boolean String Object Symbol(唯一值) BigInt(ES10未来 任意精度整数)
引用类型:Object类 --- 常规名值对的无序对象{a: 1} 数组:[1, 2] 函数等
1、基本类型 --- 名值都储存再栈内存中; let a = 1
当 b = a 复制时; 栈内存会新开辟一个内存
所以当你修改 a = 2 时 b 的值并不会发生改变 但这也算不上深拷贝 因为深拷贝都是针对于较为复杂的object类型
2、引用类型 名存栈内存中 值存堆内存中 但是栈内存会提供一个引用地址指向堆内存中的值
所以当 a = b 进行拷贝的时候 复制的是 a 的引用地址 而非堆里面的值
当我们 a [0] = 7 时 由于 a 和 b 指向的都是同一个堆内存值 所以 a 的修改 影响到了 b 这就是所谓的浅拷贝
所以要实现深拷贝 就是要在堆内存中新建一个 b 的堆内存
实现深拷贝
function deepClone(obj){
let a = JSON.stringify(obj);
b = JSON.parse(a)
return b
}
let a = [0, 1, [3,4], 9]
b = deepClone(a)
a[2][0] = 7
console.log(a, b) //[0,1,[7,4],9] [0, 1, [3,4], 9]
JSON.stringify() 和 JSON.parse() 的区别
JSON.stringify() 将对象转换为 JSON字符串 而 JSON.parse() 则是将JSON字符串转换为 对象
但是在使用JSON.parse()时 所转换的JSON字符串必须要符合JOSN格式 即键值都需要 "" 进行包裹
let a = '["1","2"]';
let b = "['1','2']";
console.log(JSON.parse(a));// Array [1,2]
console.log(JSON.parse(b));// 报错
递归方式实现:
function deepClone(obj){
let objClone = Array.isArray(obj)?[]:{};
if(obj && typeof obj==="object"){
for(key in obj){
if(obj.hasOwnProperty(key)){
//判断ojb子元素是否为对象,如果是,递归复制
if(obj[key]&&typeof obj[key] ==="object"){
objClone[key] = deepClone(obj[key]);
}else{
//如果不是,简单复制
objClone[key] = obj[key];
}
}
}
}
return objClone;
}
let a=[1,2,3,4],
b=deepClone(a);
a[0]=2;
console.log(a,b);
数组放 splice concat slice 都不是真正的深拷贝 在一级层级是没问题的 当有二层层级时 就会被影响
let a=[1,2,3,4],
b=a.slice();
a[0]=2;
console.log(a,b);
let a=[0,1,[2,3],4], b=a.slice();
a[0]=1; a[2][0]=1; console.log(a,b);
原文地址:https://www.cnblogs.com/qlb-7/p/12957968.html
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- laravel框架 laravel-admin上传图片到oss的方法
- php实现推荐功能的简单实例
- php实现登录页面的简单实例
- Laravel 自带的Auth验证登录方法
- laravel实现上传图片的两种方式小结
- Laravel开启跨域请求的方法
- Laravel 5.4前后台分离,通过不同的二级域名访问方法
- Yii框架数据库查询、增加、删除操作示例
- 在laravel5.2中实现点击用户头像更改头像的方法
- laravel 多图上传及图片的存储例子
- Laravel 添加多语言提示信息的方法
- Laravel框架表单验证操作实例分析
- Thinkphp5.0框架视图view的模板布局用法分析
- laravel5环境隐藏index.php后缀(apache)的方法
- php实现对文件压缩简单的方法