【前端面试小册】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 根本原因

  1. 重写问题:Array、Function等类型作为Object的实例,都重写了toString()方法
  2. null/undefined问题:这两个值没有toString()方法,会报错
  3. 目的不同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()不能用于类型判断,掌握各种类型判断方法的优缺点
#前端面试#
全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务