Jinuss's blog Jinuss's blog
首页
  • 源码合集

    • Leaflet源码分析
    • Openlayers源码合集
    • vue3源码
  • HTML
  • CSS
  • 技术文档
  • GitHub技巧
  • 学习
  • 实用技巧
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

东流

Web、WebGIS技术博客
首页
  • 源码合集

    • Leaflet源码分析
    • Openlayers源码合集
    • vue3源码
  • HTML
  • CSS
  • 技术文档
  • GitHub技巧
  • 学习
  • 实用技巧
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • React

  • Vue

  • JavaScript文章

    • Map和WeakMap
    • Set和WeakSet
    • ES5面向对象
    • ES6面向对象
    • 多种数组去重性能对比
    • 几个高级的JS API
    • JS随机打乱数组
    • 判断是否为移动端浏览器
    • 防抖与节流函数
    • JS获取和修改url参数
    • 比typeof运算符更准确的类型判断
    • Navigator clipboard介绍使用
    • Javascript 语法错题集
    • ESM和CommonJS详解
    • ColorThief的介绍与使用
    • new命令原理
    • 扩展运算符
    • 遍历深层对象指定层级的属性
    • 一文弄懂typeof和instanceof
      • 引言:JavaScript的类型迷宫
      • 第一章:typeof - 快速身份识别器
        • typeof的优势:
        • typeof的局限:
        • 适用场景:
      • 第二章:instanceof - 家族血统鉴定师
        • instanceof的优势:
        • instanceof的局限:
        • 适用场景:
      • 第三章:typeof vs instanceof 实战对决
      • 第四章:其他类型侦探工具
        • 1. Array.isArray() - 数组专家
        • 2. Object.prototype.toString.call() - 万能侦探
        • 3. constructor属性 - 血统追踪器
        • 4. 鸭子类型 - 行为主义者
      • 第五章:现代JavaScript的类型侦探工具
        • 1. 可选链操作符(?.) - 安全访问专家
        • 2. 空值合并运算符(??) - 默认值专家
        • 3. 类型守卫 - TypeScript的超级侦探
      • 第六章:如何选择合适的侦探工具
      • 第七章:实际应用场景
        • 场景1:表单验证
        • 场景2:API响应处理
        • 场景3:多态函数
      • 结语:成为JavaScript类型侦探大师
    • JS中可迭代的数据类型
    • 比较两个字符串的大小
    • requestIdleCallback
  • 学习笔记

  • openlayers

  • threejs

  • MapboxGL

  • 工具

  • 源码合集

  • ECMAScript历年新特性

  • 前端
  • JavaScript文章
东流
2025-08-06
目录

一文弄懂typeof和instanceof

# JavaScript类型侦探:instanceof vs typeof的奇妙冒险

# 引言:JavaScript的类型迷宫

在JavaScript的世界里,数据类型就像变色龙一样善变。有时我们需要准确识别这些"变色龙"的真实身份,这时instanceof和typeof就成了我们的侦探工具。但它们各有所长,也各有局限。今天,我们就来探索这两个侦探的秘密武器,以及它们的替代方案。

# 第一章:typeof - 快速身份识别器

typeof是JavaScript中最基础的类型检查工具,它能快速告诉我们一个值的基本类型。

console.log(typeof "Hello");      // "string"
console.log(typeof 42);           // "number"
console.log(typeof true);         // "boolean"
console.log(typeof undefined);    // "undefined"
console.log(typeof null);         // "object" (历史遗留问题!)
console.log(typeof []);           // "object"
console.log(typeof {});           // "object"
console.log(typeof function(){}); // "function"
1
2
3
4
5
6
7
8

# typeof的优势:

  • 简单直接:语法简单,使用方便
  • 基本类型友好:对原始类型判断准确
  • 安全可靠:不会抛出错误,即使变量未声明

# typeof的局限:

  • 对象类型模糊:所有对象(数组、日期等)都返回"object"
  • null问题:著名的历史遗留问题,typeof null返回"object"
  • 无法区分对象子类型:无法区分数组、日期等具体对象类型

# 适用场景:

  • 检查变量是否已定义:if (typeof variable !== 'undefined')
  • 区分基本类型和对象
  • 快速检查函数类型

# 第二章:instanceof - 家族血统鉴定师

instanceof检查对象是否属于特定构造函数或类的实例,关注的是原型链上的继承关系。

class Animal {}
class Dog extends Animal {}

const fido = new Dog();

console.log(fido instanceof Dog);    // true
console.log(fido instanceof Animal);  // true
console.log(fido instanceof Object);  // true

const arr = [];
console.log(arr instanceof Array);   // true
console.log(arr instanceof Object);  // true

const date = new Date();
console.log(date instanceof Date);   // true
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# instanceof的优势:

  • 识别对象子类型:能区分数组、日期等具体对象类型
  • 检查继承关系:可以检查对象是否在某个原型链上
  • 自定义类型识别:适用于自定义类和构造函数

# instanceof的局限:

  • 基本类型无效:对原始类型不起作用
  • 跨窗口问题:iframe或不同全局环境中的对象无法正确判断
  • 可能被欺骗:通过修改原型链可以影响结果

# 适用场景:

  • 检查对象是否是特定类的实例
  • 验证数组类型(比typeof更准确)
  • 处理自定义对象类型
  • 检查对象是否实现了某个接口(通过原型链)

# 第三章:typeof vs instanceof 实战对决

让我们通过实际场景看看两位侦探的表现:

// 场景1:检查数组
const myArray = [1, 2, 3];

console.log(typeof myArray);      // "object" - 不够具体
console.log(myArray instanceof Array); // true - 完美!

// 场景2:检查数字
const myNumber = 42;

console.log(typeof myNumber);     // "number" - 正确
console.log(myNumber instanceof Number); // false - 失败!

// 场景3:检查null
const myNull = null;

console.log(typeof myNull);       // "object" - 错误!
// console.log(myNull instanceof Object); // 报错!

// 场景4:自定义类
class Pizza {}
const myPizza = new Pizza();

console.log(typeof myPizza);      // "object" - 不够具体
console.log(myPizza instanceof Pizza); // true - 完美!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

对决结果:

  • 基本类型:typeof胜出
  • 对象类型:instanceof胜出
  • null检查:两者都失败

# 第四章:其他类型侦探工具

# 1. Array.isArray() - 数组专家

专门解决数组检测问题:

console.log(Array.isArray([])); // true
console.log(Array.isArray({})); // false
1
2

# 2. Object.prototype.toString.call() - 万能侦探

最精确的类型检测方法:

console.log(Object.prototype.toString.call([])); // "[object Array]"
console.log(Object.prototype.toString.call({})); // "[object Object]"
console.log(Object.prototype.toString.call(null)); // "[object Null]"
console.log(Object.prototype.toString.call(42)); // "[object Number]"
1
2
3
4

# 3. constructor属性 - 血统追踪器

访问对象的构造函数:

const arr = [];
console.log(arr.constructor === Array); // true

function Car() {}
const myCar = new Car();
console.log(myCar.constructor === Car); // true
1
2
3
4
5
6

注意:constructor属性可以被修改,不够可靠

# 4. 鸭子类型 - 行为主义者

"如果它走起来像鸭子,叫起来像鸭子,那它就是鸭子"

// 检查是否是类数组对象
function isArrayLike(obj) {
    return obj && 
           typeof obj.length === 'number' && 
           typeof obj[0] !== 'undefined';
}

console.log(isArrayLike([])); // true
console.log(isArrayLike({length: 0})); // true
console.log(isArrayLike("hello")); // true
1
2
3
4
5
6
7
8
9
10

# 第五章:现代JavaScript的类型侦探工具

# 1. 可选链操作符(?.) - 安全访问专家

const user = {
    address: {
        street: "Main St"
    }
};

// 安全访问嵌套属性
console.log(user?.address?.street); // "Main St"
console.log(user?.contacts?.email); // undefined (不会报错)
1
2
3
4
5
6
7
8
9

# 2. 空值合并运算符(??) - 默认值专家

const name = null;
console.log(name ?? "Anonymous"); // "Anonymous"

const age = 0;
console.log(age ?? 21); // 0 (不会误判0)
1
2
3
4
5

# 3. 类型守卫 - TypeScript的超级侦探

在TypeScript中,我们可以创建自定义类型守卫:

function isFish(pet: Fish | Bird): pet is Fish {
    return (pet as Fish).swim !== undefined;
}

const myPet: Fish | Bird = getPet();

if (isFish(myPet)) {
    myPet.swim(); // TypeScript知道myPet是Fish
} else {
    myPet.fly(); // TypeScript知道myPet是Bird
}
1
2
3
4
5
6
7
8
9
10
11

# 第六章:如何选择合适的侦探工具

  1. 基本类型检查:使用typeof

    • 检查字符串、数字、布尔值等
    • 检查变量是否定义
  2. 对象类型检查:

    • 数组:优先使用Array.isArray()
    • 其他内置对象:使用instanceof
    • 自定义对象:使用instanceof
  3. 精确类型识别:使用Object.prototype.toString.call()

  4. 安全访问:使用可选链?.和空值合并??

  5. 类型安全开发:使用TypeScript

# 第七章:实际应用场景

# 场景1:表单验证

function validateFormField(value) {
    if (value === null || value === undefined) {
        return "值不能为空";
    }
    
    if (typeof value === "string" && value.trim() === "") {
        return "字符串不能为空";
    }
    
    if (typeof value === "number" && isNaN(value)) {
        return "数字无效";
    }
    
    return "验证通过";
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 场景2:API响应处理

async function fetchUserData() {
    try {
        const response = await fetch("/api/user");
        const data = await response.json();
        
        // 检查是否是期望的数据结构
        if (data && typeof data === "object" && 
            Array.isArray(data.posts) && 
            typeof data.name === "string") {
            return data;
        }
        
        throw new Error("无效的响应格式");
    } catch (error) {
        console.error("获取用户数据失败:", error);
        return null;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 场景3:多态函数

function calculateArea(shape) {
    if (shape instanceof Rectangle) {
        return shape.width * shape.height;
    }
    
    if (shape instanceof Circle) {
        return Math.PI * shape.radius ** 2;
    }
    
    if (Array.isArray(shape) && shape.length === 2) {
        // 处理 [width, height] 数组
        return shape[0] * shape[1];
    }
    
    throw new Error("不支持的形状类型");
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 结语:成为JavaScript类型侦探大师

在JavaScript的世界里,没有完美的类型检测工具,只有最适合当前场景的选择:

  • typeof是你的基础工具包,适合快速识别基本类型
  • instanceof是你的专业工具,用于检查对象血统
  • 其他方法如Array.isArray()和Object.prototype.toString.call()是你的专业助手

真正的JavaScript侦探大师会根据不同场景灵活选择工具,有时甚至组合使用多种方法。记住,理解这些工具的原理和局限比记住它们的用法更重要。

现在,你已经准备好面对JavaScript类型系统的任何挑战了!出发吧,类型侦探!

编辑 (opens new window)
上次更新: 2025/08/07, 01:44:52
遍历深层对象指定层级的属性
JS中可迭代的数据类型

← 遍历深层对象指定层级的属性 JS中可迭代的数据类型→

最近更新
01
requestIdleCallback
08-28
02
比较两个字符串的大小
08-28
03
computed
08-26
更多文章>
Theme by Vdoing | Copyright © 2024-2025 东流 | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式