前段时间出去找工作出去面试,面试官问了一个深拷贝和浅拷贝的问题,我就随便回答了一下深拷贝和浅拷贝的方法,也没太在意。后来在整理知识点的时候又翻出来了js栈内存和堆内存,才恍然大悟,深拷贝和浅拷贝不仅仅是如何拷贝的问题。它更多的是问js变量在内存中是怎样的一种存储方式。在这里我们先来总结这几个知识点以及他们的关系:
1.js变量类型
2.堆内存和栈内存
3.深拷贝和浅拷贝
js数据类型
js数据类型分为两种:基本数据类型和引用数据类型
基本数据类型有:string number unll undefind Boolean ES6新增加了一种Symbol(独一无二的数据)
引用数据类型包括:object array function
栈内存和堆内存
栈内存:基本数据类型的值直接存在栈内存中
堆内存:引用类型的变量是存在栈内存中的指针,这个指针指向堆内存中具体的值
深拷贝和浅拷贝
深拷贝和浅拷贝的区别在于拷贝之后新的变量改变时会不会影响原来的变量,当新的变量改变时原来的变量随之改变的,即为浅拷贝,反之则为深拷贝。
首先举个浅拷贝的例子:
var a = {name:"xiaoming"}
var b = a
b.name = "xiaohong"
console.log(a.name) // "xiaohong"
b的name改变a的name也会改变,这是因为a复制给b的时候只是复制了一个a的指针地址,实际上a和b指向的以同一个堆内存中的值,因此改变的是同一个值。
因为基本数据类型都是存在栈内存的,所以也就不存在深拷贝和浅拷贝的问题
在实际工作中可能并不想让a随着b改变,下面介绍一种简单粗暴的深拷贝方法:
var a = {name:"xiaoming"}
var b = JSON.prase(JSON.stringify(a))
b.name = "xiaohong"
console.log(a.name) // "xiaoming"
JSON.stringfiy()能够将对象转换为字符串,字符串会存在栈内存中,JSON.prase()又将栈内存中的字符串转成对象,同时存在堆内存中,这样堆内存中就存在两个name,一个a所指向,一个b所指向,互不影响。