JavaScript 数据类型
核心概念
JavaScript 是一种弱类型且动态类型的语言。这意味着变量没有类型限制,可以随时被赋予不同类型的值。
目前的 JavaScript 标准(ECMAScript)共定义了 8 种数据类型,可以分为两大类:基本数据类型 和 引用数据类型。
1. 基本数据类型
基本数据类型的值是不可变的,并且直接保存在栈内存中。共有 7 种:
- Undefined:表示变量已声明但未初始化。
- Null:表示一个空对象指针(虽然
typeof null 是 'object',这是一个历史遗留 bug)。
- Boolean:只有
true 和 false 两个值。
- String:文本数据,JavaScript 中的字符串是不可变的。
- Number:基于 IEEE 754 标准的双精度 64 位浮点数。包括特殊的
NaN (Not a Number) 和 Infinity。
- Symbol (ES6):表示独一无二的值,常用于对象属性名,防止冲突。
- BigInt (ES2020):用于表示任意精度的整数,可以安全地存储和操作大整数(超过
Number.MAX_SAFE_INTEGER 的数)。
2. 引用数据类型
引用数据类型是对象。它们的值是可变的,引用地址保存在栈内存中,而实际的对象实体保存在堆内存中。
常见的引用类型包括:
- Object:普通对象
{ kwargs: '...' }
- Array:数组
[1, 2, 3]
- Function:函数(是一种特殊的对象,拥有可执行代码)
- Date、RegExp、Map、Set 等内置对象。
3. 类型检测方式
面试中常考如何准确判断数据类型,主要有以下 4 种方式:
(1) typeof
typeof 适合判断基本类型(除了 null)。
typeof 'str' // 'string'
typeof 123 // 'number'
typeof true // 'boolean'
typeof Symbol() // 'symbol'
typeof undefined // 'undefined'
typeof 10n // 'bigint'
typeof function(){} // 'function' (特殊)
typeof null // 'object' (缺陷,历史 bug)
typeof [] // 'object'
typeof {} // 'object'
(2) instanceof
instanceof 用于判断对象是否属于某个构造函数的实例,其原理是检查构造函数的 prototype 属性是否出现在对象的原型链上。
[] instanceof Array // true
{} instanceof Object // true
function(){} instanceof Function // true
// 缺陷:
// 1. 只能判断引用类型,不能判断基本类型(除非使用包装对象)
// 2. 也是基于原型链的,如果原型链被修改,结果可能不准
(3) constructor
通过访问对象的构造函数属性。
(1).constructor === Number // true
[].constructor === Array // true
// 缺陷:
// constructor 属性可以被随意修改,不可靠。
(4) Object.prototype.toString.call (最推荐)
这是最准确的类型判断方式,可以区分所有内置类型。
const getType = (val) => Object.prototype.toString.call(val).slice(8, -1);
getType(1) // 'Number'
getType('str') // 'String'
getType(null) // 'Null'
getType(undefined) // 'Undefined'
getType([]) // 'Array'
getType({}) // 'Object'
getType(/a/) // 'RegExp'
4. 类型转换
类型转换分为显式转换和隐式转换。
显式转换
通过 Number(), String(), Boolean() 等函数强制转换。
隐式转换
主要发生在运算符操作时,例如 == 比较、+ 运算、if 条件判断等。
常见坑点:
[] == ![] -> true (具体转换过程略复杂,建议查看具体面试题分析)
1 + '2' -> '12' (字符串拼接)
1 - '2' -> -1 (数字运算)
5. 面试高频问题
Q:null 和undefined 的区别?
A:
undefined 表示“未定义”,通常是变量声明了但未赋值,或者函数没有返回值。
null 表示“空值”,是一个空对象指针,通常用来表示“这里应该有一个对象,但是现在没有”。
Q: 为什么0.1 + 0.2 !== 0.3?
A: 因为 JavaScript 使用 IEEE 754 双精度浮点数。计算机二进制无法精确表示 0.1 和 0.2,相加后会产生微小的精度丢失。解决办法是使用 toFixed 或转为整数计算,或者使用 BigInt (针对整数) / 第三方库 (如 decimal.js)。