首页 > 其他分享 >浅析深拷贝和浅拷贝

浅析深拷贝和浅拷贝

时间:2023-03-23 22:27:05浏览次数:44  
标签:instanceof obj 对象 Object 数据类型 拷贝 浅析

浅析深拷贝和浅拷贝

深拷贝和浅拷贝是面试中经常会被问到的问题,手写深拷贝也是前端手撕题的热点。那么,为什么面试官们都热衷于让大家手写深拷贝呢?当然不只是看你默写代码,这其实主要是为了考察其中所涉及的JavaScript的基础知识。

数据类型

基本数据类型和引用数据类型

首先,为什么会有深浅拷贝?其源头就是因为在JavaScript中,存在两大数据类型:

  • 基本数据类型:String、Number、Boolean、Null、Undefined、Symbol、BigInt
  • 引用数据类型:Object

基本数据类型的特点是数据直接存储在中;

引用数据类型的特点是存储在栈中的是对象的引用地址,而真实的数据存放在内存中。

堆和栈

栈:

  • 栈会自动分配内存空间,占据固定大小的空间会自动释放,存放基本类型
  • 定义变量的方法执行结束,内存栈会销毁
  • 存取速度比堆快,仅次于直接位于CPU中的寄存器,数据可以共享
  • 存在栈中的数据大小与生存期必须是确定的,缺乏灵活性

堆:

  • 动态分配的内存,大小不定也不会自动释放,存放引用类型

  • 堆内存中的对象再方法结束后,这个对象还可能被另一个引用变量所引用(参数传递)

变量复制

基本数据类型的复制

let a = "你好";
let b = a;
b = "不好"
console.log(a); //"你好"

由示例可知,a、b是基本数据类型,数据存储在栈中,复制a相当于新开一个栈存储数据,所以改变b的值不会对a有影响

引用数据类型的复制

let arr1 = [1,2,3]
let arr2 = arr1;
arr2[1] = "two"
console.log(arr1); //[1,"two",3]

由示例可知,arr1、arr2是引用数据类型,其真实数据存放在堆内存,而在栈中只存储地址值。复制arr1即仅仅只复制了其地址值,该地址指向同一个堆内存。改变arr2的值,arr1的值也会改变。

深拷贝和浅拷贝

浅拷贝

浅拷贝:是指只拷贝一层,如果属性是基本类型,拷贝的就是基本类型的值;如果属性时引用类型,拷贝的就是内存地址,拷贝前后的对象,因为引用类型共享了同一块堆内存,修改会相互影响

在JavaScript中,存在浅拷贝的现象有:

  • Object.assign():当对象只有单层是深拷贝,多层则是浅拷贝
  • Array.prototype.slice(),Array.prototype.concat()
  • 使用拓展运算符实现的复制

深拷贝

深拷贝:是递归拷贝深层次,属性为对象时,开辟一个新的栈,两个对象的属性完全相同,但是对应两个不同的地址,修改一个对象的属性, 不会改变另一个对象的属性

常见的深拷贝方式有:

  • _.cloneDeep()
  • jQuery.extend()
  • JSON.parse(JSON.stringify()):当对象中有function,Symbol(),undefined时,会造成数据丢失

手写深拷贝

function deepClone(obj, hash = new WeakMap()) {
  if (obj === null) return obj; // 如果是null或者undefined我就不进行拷贝操作
  if (obj instanceof Date) return new Date(obj);
  if (obj instanceof RegExp) return new RegExp(obj);
  // 可能是对象或者普通的值  如果是函数的话是不需要深拷贝
  if (typeof obj !== "object") return obj;
  // 是对象的话就要进行深拷贝
  if (hash.get(obj)) return hash.get(obj);
  let cloneObj = new obj.constructor();
  // 找到的是所属类原型上的constructor,而原型上的 constructor指向的是当前类本身
  hash.set(obj, cloneObj);
  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      // 实现一个递归拷贝
      cloneObj[key] = deepClone(obj[key], hash);
    }
  }
  return cloneObj;
}

js自带的属性实现深拷贝,会忽略undefined、symbol和函数,以上循环递归函数可以包含各种情况。该循环递归函数多次用到了数据类型检测

typeof 数据类型检测

1、typeof不能判断null和array,结果都是“object”,一般用来检测基本数据类型

2、typeof检测function返回是“function”

instanceof检测引用数据类型

1、语法:A/object instanceof B/constructor

即B函数的显示原型对象再A对象的原型链上,返回true,否则false

[] instanceof Array; //true
{} instanceof Object;//true
new Date() instanceof Date;//true
function Person(){};
new Person() instanceof Person;
[] instanceof Object; //true
new Date() instanceof Object;//true
new Person instanceof Object;//true 

从示例可以看出,instanceof能够正确判断[]是Array的实例对象,但是不能辨别[]不是Object的实例对象。这里又涉及到原型和原型链的知识了

原型和原型链

1、构造函数和实体对象的关系

  • 函数的显示原型指向的对象默认是空Object实例对象(但Object不满足)
  console.log(Fn.prototype instanceof Object)
  console.log(Function.prototype instanceof Object)
  console.log(Object.prototype instanceof Object) //false 
  • 所有函数的实例都是Function的实例(包括Function)

  • Object的原型对象是原型链的尽头

3、constructor根据数据类型和构造函数返回类型,无法判断null和undefined

标签:instanceof,obj,对象,Object,数据类型,拷贝,浅析
From: https://www.cnblogs.com/moeyi/p/17249694.html

相关文章

  • Python对象的比较、拷贝
    '==' VS 'is'等于(==)和is是Python中对象比较常用的两种方式。简单来说,'=='操作符比较对象之间的值是否相等,而'is'操作符比较的是对象的身份标识是否相等,即它们是否是......
  • C#:.NET深拷贝和浅拷贝
    .NET中的深拷贝和浅拷贝是指对象复制的方式。浅拷贝只复制对象的引用,而不复制对象本身,因此两个对象会共享同一个引用。深拷贝则是复制对象本身,而不是复制对象的引用,因此两......
  • Apache Kafka JNDI注入(CVE-2023-25194)漏洞复现浅析
    关于ApacheKafka是一个开源的分布式事件流平台,被数千家公司用于高性能数据管道、流分析、数据集成和任务关键型应用程序。影响版本2.4.0<=Apachekafka<=3.2.2环境......
  • 深拷贝和浅拷贝是什么,有什么区别?
    深拷贝和浅拷贝是关于对象拷贝的概念,用于描述在复制一个对象时,复制的是对象本身还是对象的引用,从而影响到新旧对象之间的关系。浅拷贝是指将一个对象复制一份,但是新旧对象......
  • 浅析Facebook的盈利模式(转)
    作为全球最大的社交网站,Facebook仍在以惊人的步伐向前迈进。在很多人看来,这样的一个网站要赚钱一定很容易,估计光靠卖卖广告就能赚很多吧。是的,没错,广告肯定是Facebook的一......
  • shell之免密登录和免密拷贝
    expect真是一个好东西,可以解决免密登录服务器和免密下载的问题。记录一下。免密登录:from heremac安装brew/usr/bin/ruby-e"$(curl-fsSLhttps://raw.githubuser......
  • container和主机(host)之间的文件拷贝
    [b]1.从container到主机(host)[/b]使用dockercp命令dockercp<containerId>:/file/path/within/container/host/path/target比如安装mysql之后,复制的到my.cnfdock......
  • KCP协议浅析
    概述KCP协议结合了TCP和UDP协议的特点,是一个快速可靠的协议。引述官方介绍:KCP是一个快速可靠协议,能以比TCP浪费10%-20%的带宽的代价,换取平均延迟降低30%-40%,且最大延......
  • scp命令拷贝文件到imx6ull开发板出错
    开发环境:ubuntu22.04  OpenSSH_8.9p1OpenSSL3.0.2根据网上资料描述是OpenSSH7.0以后的版本不再支持ssh-dss(DSA)算法。解决办法:在ubuntu22.04下修改/etc/ssh/ssh_co......
  • [CVPR2020] RandLA-Net: Efficient Semantic Segmentation of Large-Scale Point Clou
    大佬的TensorFlow代码:here另一个大佬的Pytorch代码:等我看完代码再贴链接,之前那个不太行keywords高分辨率点云——约\(10^5\)点云语义分割多层次特征在正式开始......