百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

前端面试题:深入理解基本类型、引用、赋值、浅拷贝、深拷贝

wxin55 2024-11-17 02:44 8 浏览 0 评论

谈到深拷贝浅拷贝,是面试中常常问到的一个面试题,特地整理方便小伙伴对此类知识点能够深入的理解。

如何区分深拷贝与浅拷贝,简单点来说,就是假设obj1复制了obj2,当修改obj1时,看obj2是否会发生变化,如果obj2也跟着变了,说明这是浅拷贝,反之如果obj2未变,那就是深拷贝。

要深刻理解浅拷贝和深拷贝的区别,那就不得不说一下基本类型数据和引用类型数据的区别。

一、基本类型数据

变量名字和值都会储存在栈内存中,js中的基本类型数据有:字符串、数值、布尔、undefined和null。例如:

var a = 'foo';
b = a; // 栈内存会开辟一个新的内存空间,此时b和a都是相互独立的
b = 'bar';
console.log(a); // 'foo'



这类操作算不上深拷贝,因为深拷贝本身只针对较为复杂的object类型数据。基本类型数据每次赋值都会开辟一块新的内存空间,因为基本类型数据占的内存毕竟很小。

二、引用类型数据

如果是引用数据类型,变量名存在栈内存中,值存在堆内存中,栈内存会提供一个引用的地址指向堆内存中的值。计算机为什么这样设计:就是因为引用数据占用内存较多。例如:

var obj1 = { a:'foo' }
var obj2 = obj1  //obj1赋值给obj2,
       // 注意:虽然是赋值,但因为obj1是引用类型数据在堆内存中占用内存较多,
      // 计算机为了节省开销,只是为obj2开辟一块栈存储地址并指向obj1的堆内存地址

obj2.a = 'bar'  //所以当修改obj2中的值以后,查看obj1也跟着影响了
console.log( obj1.a )//bar


注意:以上操作修改obj2的同时obj1也修改了,但这不属于浅拷贝,这只是赋值操作。


延伸:

var obj1 = { a:'foo' }
var obj2 = obj1  //obj1赋值给obj2,
       // 注意:虽然是赋值,但因为obj1是引用类型数据在堆内存中占用内存较多,
      // 计算机为了节省开销,只是为obj2开辟一块栈存储地址并指向obj1的堆内存地址
obj2 = { a:'bar' }  //注意:这是字面量创建对象,并且开辟了一个新的栈和堆内存空间,
                    //和obj1没有了关系
obj2.a = 'bar'  //所以当修改obj2中的值以后,查看obj1未跟着影响
console.log( obj1.a )//foo


三、浅拷贝

简单的理解就是拷贝了对象的第一层属性,如果对象的某个属性还有第二层,第三层的数据等更多层的数据,浅拷贝是访问不到的。比如说某个属性的值是对象或数据,那浅拷贝无法复制该对象的数据。注意:诸如( var obj1 = {}; var obj2 = obj1 )的直接赋值操作不属于浅拷贝。

3.1 最简单的实现拷贝的方式为for ...in实现

function copy(data){
    var newData

    if (Object.prototype.toString.call(data) == '[object Array]') { //判断数组
        newData = []
    } else if (Object.prototype.toString.call(data) == '[object Object]') { //判断对象
        newData = {}
    }

    for (var attr in data) { //for...in只拷贝了一层
        newData[attr] = data[attr]
    }
    return newData
}


3.2Object.assign方法

function copy(data){
    var newData

    if (Object.prototype.toString.call(data) == '[object Array]') { //判断数组
        newData = []
    } else if (Object.prototype.toString.call(data) == '[object Object]') { //判断对象
        newData = {}
    }

    for (var attr in data) { //for...in只拷贝了一层
        newData[attr] = data[attr]
    }
    return newData
}

3.3 ...spread展开运算符实现

var obj = { a:'foo',b:'bar' }
var newObj = { ...obj } //展开运算符实现浅拷贝
obj.a = 1
console.log( newObj.a )//foo

四、深拷贝实现方式

4.1 浅拷贝+递归

var obj1 = {
    a: 'foo'
}
var obj2 = {
    b: 'bar'
}
var newObj= {}
Object.assign(newObj,obj1,obj2); //实现浅拷贝
obj1.a = 1;
console.log(newObj.a) // foo

4.2 通过json方法 JSON.parse(JSON.stringify())

var obj = { a:'foo',b:'bar' }
var newObj = { ...obj } //展开运算符实现浅拷贝
obj.a = 1
console.log( newObj.a )//foo

注意:json方法实现深拷贝有问题,如果源数据中有函数,则会丢失。

var obj1 = {
    a: 'foo',
    fn:function(){
        console.log('fn handle')
    }
}
let obj2 = JSON.parse(JSON.stringify(obj1 )); //方法会丢失
obj2.fn() //obj2.fn is not a function

4.3 函数库lodash

var _ = require('lodash');
var obj1 = {
    a:'foo'
};
var obj2 = _.cloneDeep(obj1); //lodash函数库实现拷贝
obj1.a = 1
console.log(obj2.a)// foo

4.4 通过jQuery的extend实现深拷贝

var obj1 = {
    a:'foo',
    b:[ 'foo','bar' ]
};
var obj2= $.extend(true,obj1); // true为深拷贝,false为浅拷贝

相关推荐

Java中List 和 Map、Set 的区别(list和set和map)

hello,大家好,我是霖仔java集合的大家了解,我再给大家说一下他们的区别,希望能够帮助到大家结构特点:List和Set是存储单列数据的集合,Map是存储键和值这样的双列数据的集合;Lis...

Java 集合框架全面解析:选对数据结构,提升开发效率

上一章我们详细介绍了各种常用的数据结构情况(参考:数据结构复杂度全览:如何选择最优结构?),本文结合关键数据结构,从列表(List)、队列(Queue)、集合(Set)、映射(Map)四个维度,深入解...

LinkedList竟然比ArrayList慢了1000多倍?(动图+性能评测)

数组和链表是程序中常用的两种数据结构,也是面试中常考的面试题之一。然而对于很多人来说,只是模糊的记得二者的区别,可能还记得不一定对,并且每次到了面试的时候,都得把这些的概念拿出来背一遍才行,未免有些麻...

LinkedList 底层源码深度解析(linkedlist底层数据结构)

目录1.引言2.LinkedList概述2.1类继承体系图2.2各个接口作用3.与ArrayList的对比4.底层数据结构5.核心方法源码解析5.1add()方法5.2a...

List的用法和实例详解——Java进阶知识讲义系列(四)

序欢迎来到全网最完整的Java进阶知识系列教程!!!每天定时更新!!!本期是Java进阶知识系列的第四讲,将分享Java常用的数据容器——集合类。集合类也分很多类型,比如:List、Set、Map、Q...

Rust高效集合操作(rust基本操作)

集合的分类Rust的集合类型主要分布在标准库的std::collections模块中,同时也包括语言内置的数组和字符串类型序列容器序列容器维护元素的顺序,适合需要按索引访问或顺序遍历的场景向量(...

Java八股文:核心知识点梳理(java八股文是啥)

一、Java基础1.Java基本数据类型8种基本类型:整型:byte(1),short(2),int(4),long(8)浮点型:float(4),double(8)字符型:char(2)布...

面试题:ArrayList和LinkedList有什么区别?

面试题

为什么我不推荐研发人员使用 LinkedList?

在Java集合框架中,LinkedList作为List的实现之一,经常被认为是ArrayList的替代方案。然而,在大多数实际场景下,我们并不推荐使用LinkedList,原因主要集中...

ArrayList 、 LinkedList、Vector的区别

ArrayList、LinkedList、Vector的区别如下:ArrayListLinkedListVector结构动态数组双向链表动态数组是否线程安全否否是效率遍历查找快,插入删除慢插入删除...

(2020 )Java最新面试笔试题答案解析(一)

Java中的集中基本数据类型是什么?各占用多少字节?【数值型】—(整数类型)byte(1字节)short(2字节)int(4字节)long(8字节)拓展:Java中的数据类型除了上面的基本...

超简单五步实现Linux虚拟机CentOS 7系统Root密码忘记重置

环境:CentOS7.5重置root密码:1.CentOS7虚拟机开机,将鼠标光标移动至虚拟机内。2.在虚拟机中使用键盘上↑和↓键将选择行设置为第一行(背景高亮即为选中),按下键盘上的e,进...

吊轨门和推拉门哪个好?北京今朝区别介绍看完不入坑

厨房到底使用什么门好?相信这是大多数业主都比较抓狂的事情,其实在装修中材料的选择最终还是要依据空间而定,那么吊轨门和推拉门哪个好呢?下面就跟随北京装修网一起来看看吧!吊轨门与推拉门介绍吊轨门吊轨门的特...

〖省钱宝典〗不花冤枉钱,少走弯路!居家中推拉门如何设计?

想要空间最大程度的显大?想要充足的光线?又想拥有合理的区域划分?那么推拉门是你绝对不能错过的好选择。推拉门的设计轻盈简洁,绝对是室内每个空间的福音。它不仅可以最大化地节省空间,方便了居室的功能划分和利...

吊趟门与推拉门有什么区别?(吊趟门贵还是推拉门贵)

吊趟门与推拉门的区别很多人在购买的时候并不清楚,有些客人甚至根本分不清吊趟门和推拉门,今天小编就给大家讲讲吊趟门与推拉门的相关内容,看看吊趟门与推拉门的区别有哪些?1、推拉门采用以门扇下滑轮为主支撑点...

取消回复欢迎 发表评论: