前端面试-JavaScript 数据类型检测全解

目录

一、基础检测方法

二、方法深度解析

1. typeof 运算符

2. instanceof 运算符

3. 终极检测方案

三、特殊场景检测方案

四、手写实现原理

1. 通用类型检测函数

2. 改进版数组检测(兼容旧浏览器)

五、常见面试陷阱

六、最佳实践指南

七、扩展知识

总结


一、基础检测方法
方法 能力范围 经典案例 注意事项
typeof 检测基本数据类型(除 null typeof 'str' → 'string' typeof null → 'object'(历史遗留问题)
instanceof 检测对象原型链 [] instanceof Array → true 跨窗口对象检测失效(如iframe)
Object.prototype.toString.call() 精确检测所有类型 toString.call([]) → '[object Array]' 需配合 call 改变 this 指向

二、方法深度解析
1. typeof 运算符
  • 返回值类型:返回类型字符串

    typeof 42;          // "number"
    typeof 'text';      // "string"
    typeof true;        // "boolean"
    typeof undefined;   // "undefined"
    typeof Symbol();    // "symbol"
    typeof 10n;         // "bigint" (ES2020+)
    typeof function(){};// "function"
    typeof {};          // "object"
    typeof [];          // "object" (缺陷)
    typeof null;        // "object" (著名陷阱)

2. instanceof 运算符
  • 原型链检测机制

    function Car() {}
    const myCar = new Car();
    myCar instanceof Car;     // true
    myCar instanceof Object;  // true(原型链追溯)

  • 跨窗口问题

    // 不同iframe中的Array构造函数不共享原型链
    iframe.contentWindow.Array !== window.Array;
    iframeArray instanceof Array; // false

3. 终极检测方案

const typeCheck = obj => {
  return Object.prototype.toString.call(obj).slice(8, -1).toLowerCase();
};

typeCheck([]);        // 'array'
typeCheck(new Date);  // 'date'
typeCheck(null);      // 'null'
typeCheck(/regex/);   // 'regexp'
typeCheck(Symbol());  // 'symbol'

三、特殊场景检测方案
检测需求 实现方案 示例
数组检测 Array.isArray() (ES5+) Array.isArray([1,2]) → true
NaN检测 Number.isNaN() (ES6+) Number.isNaN(NaN) → true
纯对象检测 组合检测 obj.constructor === Object && Object.getPrototypeOf(obj) === Object.prototype
Promise检测 obj instanceof Promise p instanceof Promise
Buffer检测 Buffer.isBuffer() (Node.js) Buffer.isBuffer(buffer)

四、手写实现原理
1. 通用类型检测函数

function getType(obj) {
  // 处理 null 的特殊情况
  if (obj === null) return 'null';
  
  // 处理基础类型(除 symbol)
  const type = typeof obj;
  if (type !== 'object') return type;

  // 处理引用类型
  const typeStr = Object.prototype.toString.call(obj);
  return typeStr.slice(8, -1).toLowerCase();
}
2. 改进版数组检测(兼容旧浏览器)

const isArray = (function() {
  if (typeof Array.isArray === 'function') {
    return Array.isArray;
  }
  return function(obj) {
    return Object.prototype.toString.call(obj) === '[object Array]';
  };
})();

五、常见面试陷阱
  1. typeof 的边界情况

    typeof NaN;           // "number"(需用 Number.isNaN 判断)
    typeof document.all;  // "undefined" (历史遗留特性)

  2. 包装对象检测

    const str = new String('test');
    typeof str;          // "object"
    str instanceof String; // true

  3. 修改对象 [[Class]] 属性

    const obj = {};
    Object.prototype.toString.call(obj); // [object Object]
    obj[Symbol.toStringTag] = 'Custom';
    Object.prototype.toString.call(obj); // [object Custom]


六、最佳实践指南
  1. 基础类型检测:优先使用 typeof

  2. 数组检测:统一使用 Array.isArray()

  3. 精确类型判断:使用 Object.prototype.toString.call()

  4. 构造函数检测:慎用 instanceof(注意原型链污染风险)

  5. 特殊值检测

    • null → obj === null

    • undefined → obj === void 0

    • NaN → Number.isNaN()


七、扩展知识
  1. ES6 新增类型检测

    const set = new Set();
    Object.prototype.toString.call(set); // [object Set]
    
    const map = new Map();
    Object.prototype.toString.call(map); // [object Map]

  2. BigInt 检测

    typeof 10n; // "bigint"

  3. 异步函数检测

    async function fn() {}
    Object.prototype.toString.call(fn); // [object AsyncFunction]


总结

掌握数据类型检测是JavaScript开发的基本功,针对不同场景选择合适的检测方案:

  • 快速判断基本类型 → typeof

  • 原型链关系验证 → instanceof

  • 精确类型识别 → Object.prototype.toString.call()

  • 特定类型优化 → 专用方法(如 Array.isArray)

理解这些方法的实现原理和边界条件,能够帮助开发者写出更健壮的代码,在面试中也能从容应对相关问题的深度追问。

你可能感兴趣的:(前端,面试,javascript)