搜索
写经验 领红包

前端基本类型和引用类型区别(前端基本数据类型和引用类型的区别)

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

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

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

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

一、基本类型数据

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

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

基本类型数据

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

二、引用类型数据

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

var obj1 = { a:&39; }var obj2 = obj1  //obj1赋值给obj2,       // 注意:虽然是赋值,但因为obj1是引用类型数据在堆内存中占用内存较多,      // 计算机为了节省开销,只是为obj2开辟一块栈存储地址并指向obj1的堆内存地址obj2.a = &39;  //所以当修改obj2中的值以后,查看obj1也跟着影响了console.log( obj1.a )//bar

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

引用类型数据

延伸:

var obj1 = { a:&39; }var obj2 = obj1  //obj1赋值给obj2,       // 注意:虽然是赋值,但因为obj1是引用类型数据在堆内存中占用内存较多,      // 计算机为了节省开销,只是为obj2开辟一块栈存储地址并指向obj1的堆内存地址obj2 = { a:&39; }  //注意:这是字面量创建对象,并且开辟了一个新的栈和堆内存空间,                    //和obj1没有了关系obj2.a = &39;  //所以当修改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) == &39;) { //判断数组        newData = []    } else if (Object.prototype.toString.call(data) == &39;) { //判断对象        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) == &39;) { //判断数组        newData = []    } else if (Object.prototype.toString.call(data) == &39;) { //判断对象        newData = {}    }    for (var attr in data) { //for...in只拷贝了一层        newData[attr] = data[attr]    }    return newData}
3.3 ...spread展开运算符实现
var obj = { a:&39;,b:&39; }var newObj = { ...obj } //展开运算符实现浅拷贝obj.a = 1console.log( newObj.a )//foo
四、深拷贝实现方式4.1 浅拷贝+递归
var obj1 = {    a: &39;}var obj2 = {    b: &39;}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:&39;,b:&39; }var newObj = { ...obj } //展开运算符实现浅拷贝obj.a = 1console.log( newObj.a )//foo

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

var obj1 = {    a: &39;,    fn:function(){        console.log(&39;)    }}let obj2 = JSON.parse(JSON.stringify(obj1 )); //方法会丢失obj2.fn() //obj2.fn is not a function
4.3 函数库lodash
var _ = require(&39;);var obj1 = {    a:&39;};var obj2 = _.cloneDeep(obj1); //lodash函数库实现拷贝obj1.a = 1console.log(obj2.a)// foo
4.4 通过jQuery的extend实现深拷贝
var obj1 = {    a:&39;,    b:[ &39;,&39; ]};var obj2= $.extend(true,obj1); // true为深拷贝,false为浅拷贝

本文内容由小快整理编辑!