【前端面试小册】JS-第1节,JavaScript数据类型详解与类型判断
1. JavaScript的10种数据类型
JavaScript中有10种数据类型,分为两大类:
1.1 基本数据类型(7种)
- Number - 数字类型
- String - 字符串类型
- Boolean - 布尔类型
- Undefined - 未定义类型
- Null - 空值类型
- Symbol - 符号类型(ES6新增)
- BigInt - 大整数类型(ES2020新增)
1.2 引用数据类型(3种)
- Object - 对象类型
- Array - 数组类型(Object的子类型)
- Function - 函数类型(Object的子类型)
面试重点:Array和Function本质上都是Object,但为了便于理解,通常单独列出。
2. 数据类型判断方法
2.1 最可靠的类型判断方法
const getType = (value) => {
return Object.prototype.toString.call(value).match(/\s+(\w+)/)[1];
}
原理解析:
Object.prototype.toString.call()
是获取对象内部[[Class]]
属性的标准方法- 返回格式:
[object TypeName]
- 通过正则匹配提取类型名称
详细使用示例:
// 测试各种数据类型的getType结果
console.log('=== 基本数据类型 ===');
console.log(getType(42)); // "Number"
console.log(getType('hello')); // "String"
console.log(getType(true)); // "Boolean"
console.log(getType(undefined)); // "Undefined"
console.log(getType(null)); // "Null"
console.log(getType(Symbol('id'))); // "Symbol"
console.log(getType(123n)); // "BigInt"
console.log('\n=== 引用数据类型 ===');
console.log(getType({})); // "Object"
console.log(getType([])); // "Array"
console.log(getType(function(){})); // "Function"
console.log(getType(new Date())); // "Date"
console.log(getType(/regex/)); // "RegExp"
console.log(getType(new Error())); // "Error"
console.log(getType(new Map())); // "Map"
console.log(getType(new Set())); // "Set"
console.log(getType(new Promise(() => {}))); // "Promise"
console.log('\n=== 特殊对象类型 ===');
console.log(getType(document)); // "HTMLDocument" (浏览器环境)
console.log(getType(window)); // "Window" (浏览器环境)
console.log(getType(Math)); // "Math"
console.log(getType(JSON)); // "JSON"
console.log(getType(console)); // "Console"
console.log('\n=== 内部处理过程演示 ===');
const testValue = [1, 2, 3];
console.log('原始值:', testValue);
console.log('toString.call结果:', Object.prototype.toString.call(testValue));
console.log('正则匹配结果:', Object.prototype.toString.call(testValue).match(/\s+(\w+)/));
console.log('最终类型:', getType(testValue));
输出结果:
=== 基本数据类型 ===
Number
String
Boolean
Undefined
Null
Symbol
BigInt
=== 引用数据类型 ===
Object
Array
Function
Date
RegExp
Error
Map
Set
Promise
=== 特殊对象类型 ===
HTMLDocument
Window
Math
JSON
Console
=== 内部处理过程演示 ===
原始值: [1, 2, 3]
toString.call结果: [object Array]
正则匹配结果: [" Array", "Array"]
最终类型: Array
与其他方法对比:
// 对比不同方法的判断结果
const testValues = [
null,
undefined,
[],
{},
function(){},
new Date(),
/regex/,
new Error(),
new Map(),
new Set()
];
console.log('值\t\t\tgetType\t\ttypeof\t\tinstanceof Array');
console.log('─'.repeat(80));
testValues.forEach(value => {
const getTypeResult = getType(value);
const typeofResult = typeof value;
const isArrayResult = value instanceof Array;
console.log(
`${String(value).substring(0, 20).padEnd(20)}\t${getTypeResult.padEnd(10)}\t${typeofResult.padEnd(10)}\t${isArrayResult}`
);
});
对比结果:
测试值 | getType | typeof | instanceof Array |
---|---|---|---|
null |
Null | object | false |
undefined |
Undefined | undefined | false |
[1,2,3] |
Array | object | true |
{} |
Object | object | false |
function(){} |
Function | function | false |
new Date() |
Date | object | false |
/regex/ |
RegExp | object | false |
new Error() |
Error | object | false |
new Map() |
Map | object | false |
new Set() |
Set | object | false |
关键优势:
- ✅
getType
能准确区分Array、Object、Function等 - ❌
typeof
无法区分Array和Object,null显示为"object" - ❌
instanceof
只能判断是否为特定构造函数的实例
2.2 类型判断工具函数
// 获取精确类型
const getType = (value) => {
return Object.prototype.toString.call(value).match(/\s+(\w+)/)[1];
}
// 判断是否为指定类型
const isType = (target, type) => {
return type.toLowerCase() === getType(target).toLowerCase();
}
// 常用类型判断函数
const isArray = (value) => isType(value, 'Array');
const isObject = (value) => isType(value, 'Object');
const isFunction = (value) => isType(value, 'Function');
const isString = (value) => isType(value, 'String');
const isNumber = (value) => isType(value, 'Number');
const isBoolean = (value) => isType(value, 'Boolean');
const isNull = (value) => isType(value, 'Null');
const isUndefined = (value) => isType(value, 'Undefined');
const isSymbol = (value) => isType(value, 'Symbol');
const isBigInt = (value) => isType(value, 'BigInt');
3. 完整示例演示
// 测试各种数据类型
const testValues = {
function: function() {},
object: {},
array: [],
undefined: undefined,
null: null,
boolean: false,
string: 'hello',
number: 42,
symbol: Symbol('id'),
bigint: BigInt(123)
};
// 测试类型判断
Object.entries(testValues).forEach(([key, value]) => {
console.log(`${key}: ${getType(value)}`);
});
// 输出结果:
// function: Function
// object: Object
// array: Array
// undefined: Undefined
// null: Null
// boolean: Boolean
// string: String
// number: Number
// symbol: Symbol
// bigint: BigInt
// 测试类型判断函数
console.log(isType(23, 'Number')); // true
console.log(isType('前端面试', 'String')); // true
console.log(isArray([1, 2, 3])); // true
console.log(isFunction(() => {})); // true
4. 为什么不能直接用toString()?
4.1 问题分析
// 直接使用toString()的问题
console.log("hello".toString()); // "hello"
console.log((123).toString()); // "123"
console.log([1,2,3].toString()); // "1,2,3"
console.log(new Date().toString()); // "Wed Dec 21 2016 20:35:48 GMT+0800"
console.log(function(){}.toString()); // "function(){}"
console.log(null.toString()); // TypeError: Cannot read property 'toString'
console.log(undefined.toString()); // TypeError: Cannot read property 'toString'
4.2 根本原因
- 重写问题:Array、Function等类型作为Object的实例,都重写了
toString()
方法 - null/undefined问题:这两个值没有
toString()
方法,会报错 - 目的不同:
toString()
用于字符串转换,不是类型判断
4.3 解决方案对比
// ❌ 错误方式
const wrongType = (value) => {
return value.toString(); // 会出错且不准确
}
// ✅ 正确方式
const correctType = (value) => {
return Object.prototype.toString.call(value).match(/\s+(\w+)/)[1];
}
5. 面试高频考点
5.1 typeof的局限性
console.log(typeof null); // "object" (历史遗留问题)
console.log(typeof []); // "object" (无法区分数组和对象)
console.log(typeof function(){}); // "function" (唯一能正确识别的引用类型)
5.2 instanceof的局限性
console.log([] instanceof Array); // true
console.log([] instanceof Object); // true (数组也是对象)
console.log(null instanceof Object); // false (null不是对象)
5.3 最佳实践
// 综合判断方案
const typeChecker = {
// 基本类型判断
isString: (value) => typeof value === 'string',
isNumber: (value) => typeof value === 'number' && !isNaN(value),
isBoolean: (value) => typeof value === 'boolean',
isUndefined: (value) => typeof value === 'undefined',
isNull: (value) => value === null,
isSymbol: (value) => typeof value === 'symbol',
isBigInt: (value) => typeof value === 'bigint',
// 引用类型判断
isArray: (value) => Array.isArray(value),
isFunction: (value) => typeof value === 'function',
isObject: (value) => value !== null && typeof value === 'object' && !Array.isArray(value),
// 通用判断
getType: (value) => Object.prototype.toString.call(value).match(/\s+(\w+)/)[1]
};
6. 实际应用场景
6.1 参数验证
function processData(data) {
const type = getType(data);
switch(type) {
case 'Array':
return data.map(item => processData(item));
case 'Object':
return Object.keys(data).reduce((acc, key) => {
acc[key] = processData(data[key]);
return acc;
}, {});
case 'String':
return data.trim().toLowerCase();
case 'Number':
return Math.round(data);
default:
return data;
}
}
6.2 深拷贝实现
function deepClone(obj) {
const type = getType(obj);
if (type === 'Array') {
return obj.map(item => deepClone(item));
}
if (type === 'Object') {
const cloned = {};
Object.keys(obj).forEach(key => {
cloned[key] = deepClone(obj[key]);
});
return cloned;
}
return obj;
}
7. 总结
- 核心方法:
Object.prototype.toString.call()
是最可靠的类型判断方法 - 避免陷阱:不要使用
typeof
判断null和数组类型 - 最佳实践:结合多种方法进行类型判断,根据具体场景选择合适的方法
- 面试重点:理解为什么
toString()
不能用于类型判断,掌握各种类型判断方法的优缺点