当前位置: 首页 > news >正文

js对象的深浅拷贝

js对象的深浅拷贝

针对于JavaScript的对象和数组(数组也是对象)浅拷贝只是引用,内存不变;而深拷贝就是递归赋值。
深拷贝是不同内存,相互独立。而浅拷贝会影响

//1.循环复制数组
var arr = [1,2,3],arr2 = [];
for(var i=0;i<arr.length;i++) {
    arr2[i] = arr[i];
}

//2.还可以用一句简单的代码实现上面的深拷贝:
Array.prototype.push.apply(arr2,arr);

//3.先把这个对象转化为字符串,在拷贝,再转化回来即可
JSON.parse(JSON.stringify(obj))

别急着走,利用window.JSON的方法做深拷贝存在2个 缺点:

  • 如果你的对象里有函数,函数无法被拷贝下来
  • 无法拷贝对象原型链上的属性和方法

例如下面这种情况:对象里包含函数

var o1 = {
    name:"小明",
    age:12,
    city:"广州",
    schools:["小学","中学","大学"],
    say:function(){
            alert(this.name);
    }
}

for...in 遍历对象,找出自身的属性,且会搜索原型,即也会查找原型上的属性
__proto__不可枚举的属性

obj.hasOwnProperty() 返回布尔值 判断属性是否是自有属性

JSON.parse(JSON.stringify(o1)) 可以将只有属性/不存在方法的对象复制
JSON.stringify 将对象转换成字符串,转换的过程,会忽略掉方法.

//下面的方法可以实现 深深度复制(复制包括函数)

function deepClone(oldObj){
        var newObj = {};
        for(var key in oldObj){
                if(oldObj.hasOwnProperty(key)){
                        if(oldObj[key].constructor == Array){ //判断oldObj[key]值是否数组/对象
                                newObj[key] = oldObj[key].slice();
                        }else if(oldObj[key].constructor == Object){
                                newObj[key] == deepClone(oldObj[key]);
                        }else{
                                newObj[key] = oldObj[key];
                        }
                }
        }
        return newObj;
}
var o2 = deepClone(o1);

当然,你明确知道他们的缺点后,如果他的缺点对你的业务需求没有影响,就可以放心使用了,一行原生代码就搞定。
目前我在开发业务场景中,大多还真可以忽略上面2个缺点。往往需要深拷贝的对象里没有函数,也不需要拷贝它原型链上的属性。


图片描述


js堆栈

由于js中的对象都是复杂数据类型,这种数据在内存中存储的时候,存放在堆中。当简单赋值的时候,其实是将该对象的指针指向同一个堆地址。
简单的数据类型存放在栈中,当对简单的数据类型进行赋值的时候,其实就是直接在栈中新开辟一个地方专门存储一样的值。

数据结构里的堆栈:
栈(stack): 由编译器自动分配, 存放函数的参数值, 局部变量的值等. 其操作方式类似于数据结构中的栈.
堆(heap): 一般由程序员分配释放, 若程序员不释放, 程序结束时可能由OS回收. 这里OS是指: 操作系统(Operating System)

相关文章:

  • ★Kali信息收集~4.DNS系列
  • Promise面试题2实现异步串行执行
  • Flex的一些总结
  • SAP ERP和C4C Account和Contact的双向同步
  • Spring源码解析—— ClassPathResource类
  • Angular6错误 Service: No provider for Renderer2
  • 01串(dp)
  • 通用排序工具类
  • Python 进行 URL 跳转
  • 安卓使用Root权限实现后台模拟全局按键、触屏事件方法(类似按键精灵)
  • 第13期 DApp 榜单 :来,吃我这波安利
  • java swing启动时窗口最大化
  • 一行代码迁移TensorFlow 1.x到TensorFlow 2.0
  • Oracle 12c 数据库中scott用户不存在的解决方法
  • redis使用场景和java测试案例
  • 「面试题」如何实现一个圣杯布局?
  • CSS进阶篇--用CSS开启硬件加速来提高网站性能
  • Docker 1.12实践:Docker Service、Stack与分布式应用捆绑包
  • Js基础知识(四) - js运行原理与机制
  • NSTimer学习笔记
  • Redis学习笔记 - pipline(流水线、管道)
  • Solarized Scheme
  • Spring Cloud Feign的两种使用姿势
  • TiDB 源码阅读系列文章(十)Chunk 和执行框架简介
  • tweak 支持第三方库
  • vue-cli3搭建项目
  • 百度贴吧爬虫node+vue baidu_tieba_crawler
  • 机器学习中为什么要做归一化normalization
  • 巧用 TypeScript (一)
  • 使用Tinker来调试Laravel应用程序的数据以及使用Tinker一些总结
  • 我建了一个叫Hello World的项目
  • 想晋级高级工程师只知道表面是不够的!Git内部原理介绍
  • Java数据解析之JSON
  • ​LeetCode解法汇总1276. 不浪费原料的汉堡制作方案
  • #include到底该写在哪
  • #我与Java虚拟机的故事#连载06:收获颇多的经典之作
  • $.ajax()
  • $Django python中使用redis, django中使用(封装了),redis开启事务(管道)
  • (12)Linux 常见的三种进程状态
  • (定时器/计数器)中断系统(详解与使用)
  • (附源码)计算机毕业设计大学生兼职系统
  • (机器学习的矩阵)(向量、矩阵与多元线性回归)
  • (简单有案例)前端实现主题切换、动态换肤的两种简单方式
  • (转)memcache、redis缓存
  • (转)ObjectiveC 深浅拷贝学习
  • .bat批处理(八):各种形式的变量%0、%i、%%i、var、%var%、!var!的含义和区别
  • .NET/C# 如何获取当前进程的 CPU 和内存占用?如何获取全局 CPU 和内存占用?
  • .NET/C# 推荐一个我设计的缓存类型(适合缓存反射等耗性能的操作,附用法)
  • .net开源工作流引擎ccflow表单数据返回值Pop分组模式和表格模式对比
  • .NET框架
  • .secret勒索病毒数据恢复|金蝶、用友、管家婆、OA、速达、ERP等软件数据库恢复
  • :如何用SQL脚本保存存储过程返回的结果集
  • @manytomany 保存后数据被删除_[Windows] 数据恢复软件RStudio v8.14.179675 便携特别版...
  • [ 第一章] JavaScript 简史
  • [C#]猫叫人醒老鼠跑 C#的委托及事件