数据类型
介绍
JavaScript 中的数据类型分为两大类:原始类型(Primitive Types)和引用类型(Reference Types)。当然也能成为基本数据类型和复杂数据类型。
当然,不论是在使用还是在读取堆栈,判断数据类型俩种数据类型还是有很大的区别的。
下面详细介绍这两种类型及其区别,并给出具体的例子。
数据类型
原始类型
原始类型包括以下几种:
Number: 数字String: 字符串- Boo`lean: 布尔值
Null: 空值Undefined: 未定义Symbol: 符号BigInt: 大整数
// Number
let num = 123;
console.log(num); // 输出: 123
// String
let str = "Hello, world!";
console.log(str); // 输出: Hello, world!
// Boolean
let bool = true;
console.log(bool); // 输出: true
// Undefined
let undef;
console.log(undef); // 输出: undefined
// Null
let n = null;
console.log(n); // 输出: null
// Symbol
let sym = Symbol("unique");
console.log(sym); // 输出: Symbol(unique)
// BigInt
let bigInt = 123456789012345678901234567890n;
console.log(bigInt); // 输出: 123456789012345678901234567890n引用类型
引用类型包括以下几种:
Object: 对象Array: 数组Function: 函数Date: 日期Map: 映射Set: 集合WeakMap: 弱映射WeakSet: 弱集合RegExp: 正则表达式
// Object
let obj = { name: "Alice", age: 30 };
console.log(obj); // 输出: { name: 'Alice', age: 30 }
// Array
let arr = [1, 2, 3];
console.log(arr); // 输出: [1, 2, 3]
// Function
let func = function () {
console.log("Hello");
};
func(); // 输出: Hello
// Date
let date = new Date();
console.log(date); // 输出: 当前日期时间
// Map
let map = new Map();
map.set("key1", "value1");
console.log(map); // 输出: Map(1) { 'key1' => 'value1' }
// Set
let set = new Set();
set.add(1).add(2).add(3);
console.log(set); // 输出: Set(3) { 1, 2, 3 }
// WeakMap
let weakMap = new WeakMap();
weakMap.set(obj, "value");
console.log(weakMap); // 输出: WeakMap { <1> entries }
// WeakSet
let weakSet = new WeakSet();
weakSet.add(obj);
console.log(weakSet); // 输出: WeakSet { <1> entries }
// RegExp
let regex = /hello/;
console.log(regex); // 输出: /hello/堆栈使用
栈(Stack)
栈是一种先进后出(Last In First Out, LIFO)的数据结构。栈主要用于存储函数调用时的局部变量和执行上下文。
特性:
- 操作简单:只有两个操作:压入(push)和弹出(pop)。
- 内存分配和释放速度快。
- 通常用于函数调用和局部变量。
function stackExample() {
let localVar = "local";
console.log(localVar); // 输出: local
}
stackExample();
console.log(localVar); // 报错:ReferenceError: localVar is not defined堆(Heap)
堆是一种动态内存区域,用于存储对象。堆中的内存分配和释放相对复杂,但提供了更大的灵活性。 特性:
- 动态分配:可以在运行时动态创建和销毁对象。
- 内存分配和释放较慢。
- 通常用于存储对象和全局变量。
function heapExample() {
let obj = { name: "Alice", age: 30 };
console.log(obj); // 输出: { name: 'Alice', age: 30 }
}
heapExample();
// 全局变量
let globalObj = { name: "Bob", age: 25 };
console.log(globalObj); // 输出: { name: 'Bob', age: 25 }区别
- 原始类型:存储在栈中,直接存储值。
- 引用类型:存储在堆中,栈中存储的是指向堆中对象的引用。
- 栈:先进后出的数据结构,主要用于存储函数调用时的局部变量和执行上下文。
- 堆:动态内存区域,用于存储对象,提供了更大的灵活性。
如何更加清晰的理解呢?
举个例子来讲:
// 原始类型直接内存值存储
let name = "Tom";
// 引用类型会将值存储在堆中,栈中存储指向堆中对象的引用
let obj1 = { a: 1 };
let obj2 = obj1;
// 如果将 引用值 修改,那么会发现: obj1 和 obj2 的值都变了,这是为什么?
// 因为 obj1 和 obj2 的值都是引用的堆的值,改的都是堆值
obj1.a = 3;可以参考下面图片:

判断数据类型
在 JavaScript 中,判断数据类型有多种方法,每种方法都有其适用场景和局限性。以下是几种常用的方法及其区别
typeof
typeof是最简单的判断数据类型的方法,主要用于判断基本数据类型。它能准确地识别string、number、boolean、undefined和symbol。
console.log(typeof "hello"); // "string"
console.log(typeof 123); // "number"
console.log(typeof true); // "boolean"
console.log(typeof undefined); // "undefined"
console.log(typeof Symbol("sym")); // "symbol"
// 对于 null 和 object 类型,typeof 返回 "object"
console.log(typeof null); // "object"
console.log(typeof {}); // "object"
console.log(typeof []); // "object"instanceof
instanceof是 JavaScript 中的一个运算符,用于判断一个对象是否是某个类的实例。它主要用于判断引用类型。
console.log([] instanceof Array); // true
console.log({} instanceof Object); // true
console.log(function () {} instanceof Function); // true
console.log(new Date() instanceof Date); // trueObject.prototype.toString.call()
Object.prototype.toString.call()可以准确判断所有类型的数据,包括null和undefined。
console.log(Object.prototype.toString.call("hello")); // "[object String]"
console.log(Object.prototype.toString.call(123)); // "[object Number]"
console.log(Object.prototype.toString.call(true)); // "[object Boolean]"
console.log(Object.prototype.toString.call(undefined)); // "[object Undefined]"
console.log(Object.prototype.toString.call(null)); // "[object Null]"
console.log(Object.prototype.toString.call([])); // "[object Array]"
console.log(Object.prototype.toString.call({})); // "[object Object]"
console.log(Object.prototype.toString.call(function () {})); // "[object Function]"
console.log(Object.prototype.toString.call(new Date())); // "[object Date]"Array.isArray()
Array.isArray()专门用于判断一个值是否为数组。
console.log(Array.isArray([])); // true
console.log(Array.isArray({})); // false
console.log(Array.isArray([1, 2, 3])); // trueBuffer.isBuffer() (Node.js)
Buffer.isBuffer()是 Node.js 中的一个方法,用于判断一个值是否为 Buffer 对象。
const buffer = Buffer.from("hello");
console.log(Buffer.isBuffer(buffer)); // true
console.log(Buffer.isBuffer({})); // false
console.log(Buffer.isBuffer([])); // false总结
typeof:简单易用,适用于基本数据类型。instanceof:适用于复杂对象类型,但需要考虑原型链的问题。Object.prototype.toString.call():适用于所有类型的数据,最准确。Array.isArray():专门用于判断数组。Buffer.isBuffer():仅在Node.js中使用,用于判断Buffer对象。