typeof 运算符与深拷贝

本文详细介绍了JavaScript中的typeof运算符如何判断基本数据类型、函数及引用类型,并探讨了深拷贝的概念及其重要性。提供了使用JSON.stringify()和JSON.parse()以及递归函数实现深拷贝的具体方法。

typeof 运算符与深拷贝

typeof 运算符

首先我们来探究 typeof 究竟能判断出来哪些数据类型。

  1. 判断值类型

    let a;
    const b = 'abc';
    const c = 100;
    const d = true;
    const e = Symbol('d');
    
    typeof(a) // "undefined"
    typeof(b) // "string"
    typeof(c) // "number"
    typeof(d) // "boolean"
    typeof(e) // "symbol"
    
  2. 判断函数

    function foo() {
    	console.log('foo')
    }
    
    typeof foo; // "function"
    
  3. 判断引用类型(不可细分)

    const a = null;
    
    const obj = {
      name: 'zhangsan'
    };
    
    const arr = [1, 2, 3, 4];
    
    const set = new Set(arr);
    
    const map = new Map();
    
    typeof a // "object"
    typeof obj // "object"
    typeof arr // "object"
    typeof set // "object"
    typeof map // "object"
    

总结

由此可以总结出:typeof 运算符可以返回五种值类型函数类型引用类型,注意这里的引用类型不可细分为数组、集合等。

深拷贝

先来看一个浅拷贝:

const obj1 = {
  name: 'xxx',
  age: 20,
  address: {
    city: 'beijing'
  },
  arr: [1, 2, 3, 4]
};

const obj2 = obj1;

obj2.name = 'yyy';
console.log(obj1.name); // yyy

这里 obj2 直接引用了 obj1 的地址,所以修改 obj2.nameobj1.name 会跟着改变。

很多时候我们并不希望得到这样的结果,但是细想为什么 javascript 甚至更多的语言在设计的时候不直接设置为深拷贝的数据呢?

其实原因很简单,设想这些语言在设计时,引用类型数据赋值后直接是深拷贝数据,那么就会特别消耗内存,当代码初始化执行时,遇到一个很大的对象时可能就会卡死。所以出于多种因素,引用类型的传递都是地址传递。

所以当我们需要得到一个引用类型数据的深拷贝时,就要通过算法来实现。这里提供两个深拷贝方法:

JSON.stringify() 和 JSON.parse()

const obj1 = {
  name: 'xxx',
  age: 20,
  address: {
    city: 'beijing'
  },
  arr: [1, 2, 3, 4]
};

// 使用 JSON.parse() 和 JSON.stringify() 实现深拷贝
const obj2 = JSON.parse(JSON.stringify(obj1));

obj2.name = 'yyy';
console.log(obj1.name); // xxx

obj2.address.city = 'shanghai';
console.log(obj1.address.city); // beijing

以上代码中我们先用方法 JSON.stringify() 方法将 obj1 对象转换为 JSON 格式的字符串,再使用 JSON.parse() 解析 JSON 格式的字符串得到对象赋值给 obj2,此时就实现了一个深拷贝。

递归

const obj1 = {
  name: 'xxx',
  age: 20,
  address: {
    city: 'beijing'
  },
  arr: [1, 2, 3, 4]
};

const obj2 = deepClone(obj1);

obj2.name = 'yyy';
console.log(obj1.name); // xxx
obj2.address.city = 'shanghai';
console.log(obj1.address.city); // beijing

function deepClone(obj = {}) {
  // 如果传进来的对象不是对象、数组或者是 null、undefined,则直接返回。
  if (typeof obj !== "object" || obj == null) {
    return obj;
  }

  // 定义一个准备返回的深克隆的变量,其类型取决于传进来的数据类型。
  const result = obj instanceof Array ? [] : {};

  // 循环遍历数组或对象,使用递归,逐层克隆数据。
  for (let key in obj) {
    // 保证 key 不是原型的属性
    if (obj.hasOwnProperty(key)) {
      // 递归调用
      result[key] = deepClone(obj[key]);
    }
  }

  return result;
}

至此我们就使用了两种方法完成了对数组、对象的深克隆。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值