在前端开发中,我们经常需要判断数据类型和进行数据拷贝操作。本文将介绍如何使用JavaScript来判断数据类型以及实现深浅拷贝。
🎨 1. 判断数据类型
在JavaScript中,我们可以使用多种方法来判断数据类型。下面是几种常用的方式:
- 使用
typeof
运算符:typeof
可以判断出基本类型的变量,例如字符串、数字、布尔值和函数。但是需要注意的是,对于null
,typeof
会返回"object"。
javascript
typeof 'hello'; // "string"
typeof 123; // "number"
typeof true; // "boolean"
typeof function() {}; // "function"
typeof null; // "object"
- 使用
instanceof
运算符:instanceof
可以判断一个对象是否是某个构造函数的实例。这对于判断自定义对象的类型非常有用。
原理是判断对象的原型链上是否存在构造函数的原型 参考 API 文档: instanceof - JavaScript | MDN (mozilla.org)
javascript
const arr = [];
arr instanceof Array; // true
- 使用
Object.prototype.toString.call()
方法:这是一种通用的判断数据类型的方法,可以区分不同的引用类型。
javascript
Object.prototype.toString.call('hello'); // "[object String]"
Object.prototype.toString.call(123); // "[object Number]"
Object.prototype.toString.call(true); // "[object Boolean]"
Object.prototype.toString.call(function() {}); // "[object Function]"
Object.prototype.toString.call(null); // "[object Null]"
三种方法各有优劣,通常采用的做法是方法一与方法三混合使用,对于基本类型的变量使用方法一来判断,对于object
类型的变量则采用方法三来判断。
🌈 2. 实现深浅拷贝
数据拷贝是在开发中经常遇到的需求,它可以帮助我们创建一个与原始数据相同或相似的新数据,以便进行独立的操作。在JavaScript中,数据拷贝可以分为浅拷贝和深拷贝两种。
浅拷贝
浅拷贝是指拷贝一个对象的引用,新对象和原对象引用同一块内存空间。当原对象发生变化时,新对象也会受到影响。
在JavaScript中,常见的浅拷贝方法有两种:
- 使用拓展运算符(
...
):拓展运算符可以将一个数组或对象展开,创建一个新的数组或对象。但是需要注意的是,它只能实现一层的浅拷贝。
javascript
const obj = { name: 'Alice', age: 20 };
const newObj = { ...obj };
- 使用
Object.assign()
方法:Object.assign()
方法可以将源对象的属性拷贝到目标对象中,也只能实现一层的浅拷贝。
javascript
const obj = { name: 'Alice', age: 20 };
const newObj = Object.assign({}, obj);
深拷贝
深拷贝是指拷贝一个对象的副本,新对象和原对象完全独立,互不影响。
在JavaScript中,常见的深拷贝方法有两种:
- 使用
JSON.parse(JSON.stringify(obj))
:这是一种简单粗暴的方法,它将原始对象先转换为JSON字符串,然后再通过JSON.parse()
方法解析为新的对象。但需要注意的是,这种方法无法拷贝函数和正则对象。
javascript
const obj = { name: 'Alice', age: 20 };
const newObj = JSON.parse(JSON.stringify(obj));
- 手动实现深拷贝:通过递归遍历原始对象,创建新的对象,并将原始对象的属性值赋值给新对象的对应属性。
javascript
function deepClone(obj, hash = new WeakMap()) {
if (obj == null) return obj;
if (obj instanceof RegExp) return new RegExp(obj);
if (obj instanceof Date) return new Date(obj);
if (typeof obj !== 'object') return obj;
// 防止循环引用
if (hash.get(obj)) return hash.get(obj);
let cloneObj = new obj.constructor();
hash.set(obj, cloneObj);
for (let key in obj) {
// 确保只拷贝自身的属性而非继承的属性
if (obj.hasOwnProperty(key))
cloneObj[key] = deepClone(obj[key], hash);
}
return cloneObj;
}