浅谈Javascript 浅拷贝和深拷贝的理解
javascript中存储对象都是存地址的。
浅拷贝:浅拷贝是都指向同一块内存区块,浅拷贝共用同一内存地址,你改值我也变。如果拷贝的对象里面的值是一个对象或者数组,它就是浅拷贝,拷贝的知识引用地址。 js的Object.assign,jquery的extend方法都是浅拷贝,一般的等号赋值也是浅拷贝 。
上面vue里面的两个写法也是浅拷贝,具体地址为 https://cn.vuejs.org/v2/guide/list.html
深拷贝:深拷贝则是另外开辟了一块区域,深拷贝是互不影响,你改值我也不变。angular里面的 angular.copy 是深拷贝。
下面实例也可以看出这一点:
// 浅拷贝
const a = {t: 1, p: 'gg'};
const b = a;
b.t = 3;
console.log(a); // {t: 3, p: 'gg'}
console.log(b); // {t: 3, p: 'gg'}
//深拷贝
const c = {t: 1, p: 'gg'};
const d = deepCopy(c);
d.t = 3;
console.log(c); // {t: 1, p: 'gg'}
console.log(d); // {t: 3, p: 'gg'}
//浅拷贝 es6 扩展运算符
let a = [,,,,];
let b = a; // 相当于copy
a.push();
console.log(a); // [14, 12, 54, 33, 22, 44]
console.log(b); // [14, 12, 54, 33, 22, 44] //深拷贝
let a = [,,,,];
let b = [...a];
a.push();
console.log(a); // [14, 12, 54, 33, 22, 44]
console.log(b); // [14, 12, 54, 33, 22]
可以明显看出,浅拷贝在改变其中一个值时,会导致其他也一起改变,而深拷贝不会。
Object.assign() ————深拷贝神器,这个方法就是用来拷贝一个对象的,通常做法就是Object.assign({}, sourceObject, { key1: value1,key2: value2}) {}表示目标对象,会定义成一个空的{},sourceObjec就是源对象
// Cloning an object
var obj = { a: 1 };
var copy = Object.assign({}, obj);
console.log(copy); // { a: 1 }
// Merging objects
var o1 = { a: 1 };
var o2 = { b: 2 };
var o3 = { c: 3 }; var obj = Object.assign(o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 }
console.log(o1); // { a: 1, b: 2, c: 3 }, target object itself is changed.
console.log(o2);//{b: 2} 源对象没有变
console.log(o3);// {c: 3}
是不是很完美,又可以clone又可以merge。在我这种情况下,我觉得我的代码量又可以减少了,比如:
const defaultOpt = {
title: 'hello',
name: 'oo',
type: 'line'
};
// 原来可能需要这样
const opt1 = deepCopy(a);
opt1.title = 'opt1';
opt1.type = 'bar';
opt1.extra = 'extra'; // 额外增加配置
// 现在只要这样
const opt2 = Object.assign({}, a, {
title: 'opt2',
type: 'bar',
extra: 'extra'
});
注:它只对顶层属性做了赋值,完全没有继续做递归之类的把所有下一层的属性做深拷贝。意思就是是拷贝一层,没有拷贝多层。
一层
{
a: 1,
b: 2,
} 多层
{
a: 1,
b: 2,
c: {
d: 4,
e: {
f: 6,
g: 7
}
}
}
实现深拷贝,遍历key
function deepClone(obj){
//判断obj是否为数组,如果是,初始化数组[],否则初始化对象{}
let dcObj = Array.isArray(obj)?[]:{};
if(obj && typeof obj==="object"){
//循环
for(key in obj){
//判断对象是否有key属性
if(obj.hasOwnProperty(key)){
//判断ojb子元素是否为对象,如果是,递归复制
if(obj[key]&&typeof obj[key] ==="object"){
dcObj[key] = deepClone(obj[key]);
}else{
//如果不是,简单复制
dcObj[key] = obj[key];
}
}
}
}
return dcObj;
};
let t1 = {
"a": 1,
"b": 2,
"c": {
"d": 4,
"e": {
"f": 6,
"g": 7
}
}
};
let t2=deepClone(t1);
t1.a=6;
console.log(t1);
/*
{
"a": 6,
"b": 2,
"c": {
"d": 4,
"e": {
"f": 6,
"g": 7
}
}
}
*/
console.log(t2); //t1深拷贝给t2, b属性的值还是为2,没有改变,所以是深拷贝
/*
{
"a": 1,
"b": 2,
"c": {
"d": 4,
"e": {
"f": 6,
"g": 7
}
}
}
*/
参考:https://www.jianshu.com/p/a66050673663
浅谈Javascript 浅拷贝和深拷贝的理解的更多相关文章
- 浅谈C#浅拷贝和深拷贝
近来爱上一本书<编写高质量代码,改善C#程序的157个建议>,我想很多人都想编写高质量的代码,因为我们不仅仅是码农,更是一名程序员. 从今天开始,我将每天和大家分享这本书中的内容,并加上自 ...
- 浅谈java浅拷贝和深拷贝
前言:深拷贝和浅拷贝的区别是什么? 浅拷贝:被复制的对象的所有变量都含有原来对象相同的值,而所有的对其他对象的引用仍然指向原来的对象.换言之, 浅拷贝仅仅复制所考虑的对象,而不复制它所引用的对象.深拷 ...
- 浅谈Java中的深拷贝和浅拷贝(转载)
浅谈Java中的深拷贝和浅拷贝(转载) 原文链接: http://blog.csdn.net/tounaobun/article/details/8491392 假如说你想复制一个简单变量.很简单: ...
- 浅谈Java中的深拷贝和浅拷贝
转载: 浅谈Java中的深拷贝和浅拷贝 假如说你想复制一个简单变量.很简单: int apples = 5; int pears = apples; 不仅仅是int类型,其它七种原始数据类型(bool ...
- 浅谈JavaScript中的闭包
浅谈JavaScript中的闭包 在JavaScript中,闭包是指这样一个函数:它有权访问另一个函数作用域中的变量. 创建一个闭包的常用的方式:在一个函数内部创建另一个函数. 比如: functio ...
- 浅谈 JavaScript 编程语言的编码规范
对于熟悉 C/C++ 或 Java 语言的工程师来说,JavaScript 显得灵活,简单易懂,对代码的格式的要求也相对松散.很容易学习,并运用到自己的代码中.也正因为这样,JavaScript 的编 ...
- 浅谈javascript的原型及原型链
浅谈javascript的原型及原型链 这里,我们列出原型的几个概念,如下: prototype属性 [[prototype]] __proto__ prototype属性 只要创建了一个函数,就会为 ...
- 浅谈JavaScript中的正则表达式(适用初学者观看)
浅谈JavaScript中的正则表达式 1.什么是正则表达式(RegExp)? 官方定义: 正则表达式是一种特殊的字符串模式,用于匹配一组字符串,就好比用模具做产品,而正则就是这个模具,定义一种规则去 ...
- 浅谈javascript函数节流
浅谈javascript函数节流 什么是函数节流? 函数节流简单的来说就是不想让该函数在很短的时间内连续被调用,比如我们最常见的是窗口缩放的时候,经常会执行一些其他的操作函数,比如发一个ajax请求等 ...
随机推荐
- mysql 常用命令 | 表间 弱关联 join
show databases; use mhxy; select database(); show tables; desc account_list_175; ),(); select from_u ...
- NSData、数据结构与数据转换
数据结构公式:Data_Structure=(D,R): 只要数据元素与数据(组织关系)能够保持:同一个数据(结构)可以在各种存贮形式间进行转换. 字节流或字符串是所有转化的中间节点(中转站).相当于 ...
- Pandas模块 --- 字符与日期型数据的处理
1,pd.to_datetime( 要转换的日期, format= ), 2,pd.to_datetime.today( ).year ,pd.to_datetime.now( ).year 3,字 ...
- podium micro-frontends 简单试用
以下是一个简单的podium 试用,包含了layout 以及podlets,使用docker 运行 podium 主要包含了两大部分 podlets 片段服务 layouts 片段组合服务 环境准备 ...
- ES6 let 和const
一.var 的缺陷:var 只有全局作用域和函数作用域,没有块级作用域,除了在函数内部的变量默认都属于window var foo='hello'; fn=function(){ var foo='w ...
- 洛谷 P1621 集合
目录 题目 思路 \(Code\) 题目 P1621 集合 思路 并查集+埃氏筛,一开始连通块的个数是\(b-a+1\)个,在筛素数的过程中只要当前素数大于\(p\)就对该素数筛出来的数进行判断,如果 ...
- 用户生命周期(User Lifetime)
什么是用户生命周期? 用户生命周期是从用户开始接触产品到离开产品的整个过程.用户生命周期可分为:引入期.成长期.成熟期.休眠期.流失期.对应的是用户对产品不同的参与程度. 用户生命周期有什么用? 按照 ...
- sharding-jdbc使用笔记
核心概念: 1.逻辑表:水平拆分的数据库(表)的相同逻辑和数据结构表的总称.例,根据主键尾数拆分为10张表,分别是t_order_0到t_order_9,他们的逻辑表名为t_order 2.真实表:在 ...
- X86 下的SSDT HOOK
目录 SSDTHOOK 1.SSDTHOOK 原理. 1.x32下的SSDT HOOK 2.SSDT HOOK代码 3.结果 4.总结 SSDTHOOK 1.SSDTHOOK 原理. x32下,直接获 ...
- ModuleNotFoundError: No module named 'suit'
ModuleNotFoundError: No module named 'suit' pip3. install suit