资讯专栏INFORMATION COLUMN

javaScript中简单数据类型和复杂数据类型赋值拷贝的理解

Julylovin / 3295人阅读

摘要:原理中的数据类型分为两类,简单数据类型和复杂数据类型简单数据类型包括数值,字符串布尔值复杂数据类型对象即属性的集合先了解数据类型在计算机中的存储简单数据类型存储的是对象的原始数据复杂数据类型对象的原型也是引用类型,对象类型的值多带带存放。

在js中将一个值a赋值给另一个值b,在什么情况下改变了b的值会影响a的值?在知道哪种类型赋值后改变值会影响原对象的情况下该怎么做才不会影响原对象?就是这里需要讨论的问题。

首先是哪种类型赋值后改变赋值后的值会影响到被赋值的值?

let a = 1;
let b = a;
b = 2;
console.log(a) // 1

let obj = {a: 1}
let obj2 = obj;
obj2.a = 2;
console.log(obj) // {a: 2}

从这里我们可以知道:简单数据类型的number赋值后就算改变赋值后的值也不会影响到其本身,但是对象复制后改变了赋值后的值就会影响到其本身。

原理:

javaScript中的数据类型分为两类,简单数据类型和复杂数据类型;
1.简单数据类型:包括数值,字符串、布尔值、null、undefined;
2.复杂数据类型:对象即属性的集合(function、Array、Object);

先了解数据类型在计算机中的存储;
1.简单数据类型:存储的是对象的原始数据;
2.复杂数据类型:对象的原型也是引用类型,对象类型的值多带带存放。对象原型的方法和属性放在内存中,通过原型链的方式来指向这个地址;所以对象类型存储的是对象的引用地址;

对象类型在复制的时候,只是将对象的引用复制了,将a对象的引用地址值赋值给了b
所以在b改变对象属性值的时候,a的引用也发生了改变,它们在内存中获取的都是同一个对象;

如果想要复制一个复杂数据类型却不想影响原对象,此时就需要用到深拷贝/浅拷贝。

浅拷贝:
首先由一个数组[1,2,3]或对象{name:"porco", age:1},这样的数组或对象中的值统一不为[数组array]或[对象obj]的只有一层数据结构的简单对象,被称为浅拷贝对象,如果单纯的赋值使用例如let a = [1,2,3],如果改变了a,那么原数组也会相应的被改变,对象也是一样。所以遇到这种情况,想要复制的对象的改变不想影响到原对象,就需要浅拷贝方法:如下

/**
* 浅拷贝对象:
**/

let obj = {a:1,b:2}
let obj2 = {};
/*方法1*/
for(let e in obj) {
    obj2[e] = obj[e]
}
/*方法2*/
Object.keys(obj).forEach(e => {
    obj2[e] = obj[e]
})
obj2.a = 0;
console.log(obj2) //{a:0, b:2}
console.log(obj) //{a:1, b:2}

/*这里还可以使用两种es6浅拷贝方式*/
/*这是直接浅拷贝:*/
let obj2 = Object.assign({}, obj);

/*以及直接使用拓展运算符拷贝*/
let obj2 = {...obj}

/*以上四种方式均可作为浅拷贝对象的方式*/

/***********************************/
 /**
 * 浅拷贝数组:
 **/
let arr = [1,2,3]
/*第一种浅拷贝数组方式*/
let arr2 = arr.slice(); 
/*第二种浅拷贝数组方式*/
let arr2 = arr.concat();
/*第三种浅拷贝数组方式*/
let arr2 = [];
arr.forEach(e => {
    arr2.push(e)
})
arr2.[0] = 0;
console.log(arr2) //[0,2,3]
console.log(arr) //[1,2,3]

深拷贝:
当对象中的第一层级有一项是数组或对象,浅拷贝失效,例如:let a = [{a:1}]或let a = {a:{aa:1}},这样,使用上面的方法都会失效。这时必须使用深拷贝
1、最简单的办法

let BBB = JSON.parse(JSON.stringify(AAA)) 

这种方法简单适用于普通场景,但是也会抛弃对象的constructor,不管之前的构造函数什么样,深拷贝后都会变成object.这种方法能正确处理的对象只有 Number, String, Boolean, Array, 并且能用jso格式直接表示的数据结构。

2、一个递归方法:

function deepClone(obj) {
    let objClone = Array.isArray(obj) ? [] : {};
    if(obj && typeof obj === "object") {
        for(let key in obj) {
            if(obj.hasOwnProperty(key)) {
                if(obj[key] && typeof obj[key] === "object") {
                    objClone[key] = deepClone(obj[key]);
                } else {
                    objClone[key] = obj[key];    
                }
             }
         } 
    }
    return objClone
}

以上就是讨论了哪些值类型赋值不需要使用拷贝,哪些值类型赋值需要浅拷贝,哪些值类型赋值需要深拷贝

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/101662.html

相关文章

  • JavaScript之浅、深拷贝

    摘要:前言里面浅拷贝和深拷贝是非常关键的知识点,今天就来通过本文清楚的了解深浅拷贝以及该如何实现这两种拷贝方式。对象的拷贝又分为浅拷贝和深拷贝。印证了上述所说的对于所有的基本类型,简单的赋值已经是实现了深拷贝。 前言 JavaScript里面浅拷贝和深拷贝是非常关键的知识点,今天就来通过本文清楚的了解深浅拷贝以及该如何实现这两种拷贝方式。 深浅拷贝的区别 拷贝:其实就是一个对象复制给另外...

    leanxi 评论0 收藏0
  • 深入理解javascript按值传递与按引用传递

    摘要:引用类型参数的传递与引用类型的复制一样,传递的是内存地址。指向一个新的地址,与不再指向同一个地址官方解释来一发中所有函数的参数都是按值传递的。总结很简单,函数参数都是按值传递都是栈内数据的拷贝。 基本类型与引用类型 值类型(基本类型):String,Number,Boolean,Null,Undefined。 引用类型:Array、Object、Function、Date等有多个值...

    陈江龙 评论0 收藏0
  • 深入理解javascript按值传递与按引用传递

    摘要:引用类型参数的传递与引用类型的复制一样,传递的是内存地址。指向一个新的地址,与不再指向同一个地址官方解释来一发中所有函数的参数都是按值传递的。总结很简单,函数参数都是按值传递都是栈内数据的拷贝。 基本类型与引用类型 值类型(基本类型):String,Number,Boolean,Null,Undefined。 引用类型:Array、Object、Function、Date等有多个值...

    hedzr 评论0 收藏0
  • JavaScript系列--浅析JavaScript解析赋值、浅拷贝拷贝区别

    摘要:它将返回目标对象。有些文章说是深拷贝,其实这是不正确的。深拷贝相比于浅拷贝速度较慢并且花销较大。拷贝前后两个对象互不影响。使用深拷贝的场景完全改变变量之后对没有任何影响,这就是深拷贝的魔力。 一、赋值(Copy) 赋值是将某一数值或对象赋给某个变量的过程,分为: 1、基本数据类型:赋值,赋值之后两个变量互不影响 2、引用数据类型:赋址,两个变量具有相同的引用,指向同一个对象,相互之间有...

    laznrbfe 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<