JS数据类型、深浅拷贝

基本数据类型有几种,null是对象类型还是基本数据类

1.基本数据类型有 numberstringbooleannullundefinedsymbol(ES6新增的),也称原始数据类型

2.JS有原始值类型引用值类型

  • 2.1 原始值类型里面存储的都是值,原始值类型是无法改变的。
var str = "hello";
str[0] = "z"; //无法修改
  • 2.2 引用值类型指的是由多个值构成的对象。
    一般情况下声明的变量是对象类型的话,会在栈内存中存放着引用地址,该地址会指向堆内存中的内容。

3.JS内存分为堆内存和栈内存,栈内存保存的都是有固定大小、空间的内容。堆内存中存储的都是不固定的内容。

  • 字符串是个特例,字符串具有不变性,字符串存储在栈内存中

4.二者区别

  • 4.1 原始值类型保存在栈内存中,可以按值直接访问。
    值与值之间是独立存在的,修改一个变量不会影响到其他变量
var a = 10;
var b = a; //将a的值赋给b
b = 20;
console.log(a); // 10
console.log(b); // 20

基本数据类型赋值过程:

图片来自博主:cc_ccc

  • 4.2 引用值类型存放在堆内存中,按照引用访问。
    • 每新建一个新的对象,就会在堆内存中开辟一块新的空间
    • 如果两个变量保存的是同一个对象引用,当通过一个变量修改属性时,另外一个也会受到影响
var obj = new Object();
obj.name = "孙悟空";
var obj2 = obj;
obj2.name = "猪八戒";
console.log(obj.name); //猪八戒
console.log(obj2.name); //猪八戒

引用数据类型赋值过程:
在这里插入图片描述
图片来自博主:cc_ccc

5.如果两个对象一模一样,但也还是两个对象

  • 当比较两个基本数据类型的值时,就是比较数值
  • 比较两个引用数据类型时,比较的是对象的内存地址,对象相同,但地址不同,会返回false

6.null不是引用数据类型,是基本数据类型。

深拷贝、浅拷贝

1.深拷贝: 修改新变量的值不会影响原有变量的值,默认情况下基本数据类型都是深拷贝

let num1 = 123;
let num2 = num1;
num2 = 666; // 修改新变量的值
console.log(num1); //123
console.log(num2); /666

2.浅拷贝:修改新变量的值会影响原有的变量的值,默认情况下引用类型都是浅拷贝。

class Person{
   name = "jjj";
   age = 23;
}
let p1 = new Person();
let p2 = p1;
p2.name = "wdhj";   //修改p2的值影响了p1的值
console.log(p2.name);   //wdhj
console.log(p1.name);   //wdhj

如何实现引用数据类型的深拷贝(上)

当引用数据类型中保存的都是基本数据类型时

1.方法一(不好)

  • 浅拷贝的原因:多个变量指向了同一块存储空间,想要实现深拷贝,可以让每个变量分别指向自己的存储空间
 class Person{
    name = "mss";
    age = 18;
 }
 let p1 = new Person();
 let p2 = new Person();
 //因为p1里面的属性都是基本数据类型,所以可以取出p1的name赋值给p2
 p2.name = p1.name; 
 p2.age = p1.age;
 p2.name = "mhf";
 p2.age = 20;
 console.log(p1.name); //mss
 console.log(p2.name); //mhf

2.方法二(不好)

  • 利用循环来遍历每个属性
 class Person{
    name = "mss";
    age = 18;
 }
 let p1 = new Person();
 let p2 = new Person();
 for(let key in p1){ //利用遍历来赋值每个属性
        p2[key] = p1[key];
    }
 p2.name = "mhf";
 console.log(p1.name);//mss
 console.log(p2.name);//mhf

3.方法三(重点)

  • Object的assign()方法接收两个参数,代表含义是将p1中的所有属性拷贝到p2中
 class Person{
    name = "mss";
    age = 18;
 }
 let p1 = new Person();
 let p2 = new Person();
 Object.assign(p2,p1);
 p2.name = "mhf";
 console.log(p1.name);//mss
 console.log(p2.name);//mhf

以上三种方法并不能实现真正意义上的深拷贝,因为对象中保存的都是基本数据类型

如何实现引用数据类型的深拷贝(下)

当引用数据类型中保存的都是引用数据类型时

  class Person{
      name = "mss";//只有name是基本数据类型
      cat = {
         age: 3,
      };
      scores = [1,2,3];
  }
  let p1 = new Person();
  let p2 = new Person();
  deepCopy(p2,p1);//调用deepCopy函数
  p2.cat.age = 666;//修改p2中cat的age属性
  console.log(p1.cat.age);//3
  //p2的修改并没有导致p1的变化
  console.log(p2.cat.age);//666

  function deepCopy(target,source) {
      //1.遍历拿到source中所有的属性
      for(let key in source){
          //2.取出遍历到的属性的取值
          let sourceValue = source[key];
          //3.判断当前的取值是否是引用数据类型
          if(sourceValue instanceof Object){ //所有的对象都是Object的实例
              //拿到对象的constructor,查看是数组还是对象
              //console.log(sourceValue.constructor);
              //是数组就new Array,是对象就new Object
              //console.log(new sourceValue.constructor);
              let subTarget = new sourceValue.constructor;
              target[key] = subTarget;
              //再次调用拷贝对象中的属性
              deepCopy(subTarget,sourceValue);
          }else{
              //如果是基本数据类型直接添加
              target[key] = sourceValue;
          }
      }
  }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值