前端深拷贝和浅拷贝的理解和学习

什么是基本数据类型和引用数据类型?

 首先在学习深拷贝和浅拷贝的提前先了解一下数据类型:

   一个变量可以存放两种类型的值,基本类型的值(primitive values)和引用类型的值(reference values)。

ES6 引入了一种新的原始数据类型 Symbol,表示独一无二的值。它是 JavaScript 语言的第七种数据类型,前六种是:Undefined、Null、布尔值(Boolean)、字符串(String)、数值(Number)、对象(Object)。

基本数据类型有6种: Undefined、Null、Boolean、Number、String、Symbol (new in ES 6) !

基本数据类型的值是按值访问的。

基本类型的值是不可变的

基本类型的比较是它们的值的比较

以上a和b的比较 ,由于数据类型不同,但是也可以进行比较,然而在比较之前会自动进行了数据类型的 隐式转换。

==  只是进行值的比较

=== 不仅是值的比较,也涉及了数据类型的比较,所以不同数据类型不同会返回false

引用类型

除过上面的 6 种基本数据类型外,剩下的就是引用类型了,统称为Object 类型。细分的话,有:Object 类型、Array 类型、Date 类型、RegExp 类型、Function 类型等

引用类型的值是可变的

引用类型的比较是引用的比较

obj1 和 obj2 分别引用的是存放在堆内存中的2个不同的对象,故变量 obj1 和 obj2 的值(引用地址)也是不一样的!

检测类型

typeof:经常用来检测一个变量是不是最基本的数据类型

例如:

instanceof:用来判断某个构造函数的 prototype 属性所指向的对象是否存在于另外一个要检测对象的原型链上

({})instanceofObject// true

([])instanceofArray// true

(/aa/g)instanceofRegExp// true

(function(){})instanceofFunction// true

以上是对基本数据类型基本了解

一、浅拷贝和深拷贝的区别

数据都是存储在内存当中,而我们调用数据的时候都是通过地址(指针)来调用数据。

对于浅拷贝来说,比如一个数组(数组是一种对象),只要我们修改了一个拷贝数组,那么原数组也会改变!

因为他们引用的是同一个地址的数据!拷贝的时候并没有给b数组创造独立的内存,只是把a数组指向数据的 指针 拷贝给了b!

而深拷贝就与其相反,将会给b数组创造独立的内存,并且将a数组的内容一一拷贝进来,两者互不影响。

二、浅拷贝和深拷贝的原理(借鉴某位博主的内容仅供参考)

浅拷贝和深拷贝一般是对于引用类型值(如对象)来讲的,而基本类型值(如undefined、null、number、string、boolean以及es6新增的Symbol),只要是复制,就一定是另开辟以存储空间!

①基本数据类型存储:名值都存在栈内存中

如let a = 1;

当let b = a时,b复制了a,栈内存会新开辟一个内存

引用数据类型:名存在栈内存中,值存在于堆内存中,但是栈内存会提供一个引用的地址指向堆内存中的值

b复制了a后,b是引用了a的值的存储地址,而不是把a的值复制了下来!

浅拷贝:

1、Object.assign()

用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。

2 、函数式实现

hasOwnProperty基本概念

hasOwnProperty() 方法会返回一个布尔值,指示对象自身属性中(非继承属性)是否具有指定的属性,

如果 object 具有带指定名称的属性,则 hasOwnProperty 方法返回 true,否则返回 false。此方法不会检查对象原型链中的属性;该属性必须是对象本身的一个成员。

三、深拷贝的实现

1、JSON.parse和JSON.stringify

对于 JSON 安全(也就是说可以被序列化为一个 JSON 字符串并且可以根据这个字符串解析出一个结构和值完全一样的对象)的对象来说,有一种巧妙的复制方法:

var b = JSON.parse(JSON.stringify(a));

b就是拷贝的结果,修改b不影响a。但是这种方法也有缺陷:

无法复制函数

原型链没了,对象就是object,所属的类没了。

你可能感兴趣的:(前端深拷贝和浅拷贝的理解和学习)