一文看懂 JS 的「类型判断和类型转换」

107 阅读4分钟

本文用最简明的语言,带你掌握 JS 类型判断与类型转换的核心方法和底层逻辑,配合实例,助你轻松复习和应用。


一、JS 的数据类型有哪些?

JavaScript 的数据类型分为两大类:

  • 基本类型(Primitive Types)stringnumberbooleanundefinednullsymbolbigint
  • 引用类型(Reference Types):如 ObjectArrayFunctionDateRegExp

二、类型判断方法全览

1. typeof:最常用的类型判断

typeof 是前端面试和开发中最常用的类型判断工具。它的用法非常简单:

console.log(typeof 123);           // "number"
console.log(typeof 'hello');       // "string"
console.log(typeof true);          // "boolean"
console.log(typeof undefined);     // "undefined"
console.log(typeof Symbol());      // "symbol"
console.log(typeof 10n);           // "bigint"

但是,typeof 有两个“坑”:

  1. 无法准确判断 null
    console.log(typeof null); 
    

image.png 这是 JS 设计早期的历史遗留问题,null 实际上是基本类型,但 typeof 却返回 "object"。

  1. 无法区分对象类型
    console.log(typeof {});         // "object"
    console.log(typeof []);         // "object"
    console.log(typeof function(){}); // "function"
    
    image.png 除了函数,其他引用类型都只会返回 "object"。

原理小科普

typeof 本质是通过值的二进制标识来判断类型。对于前三位为 0 的,都会被识别为对象类型,而所有引用类型的二进制前三位都是 0,null 的二进制全是 0,所以也被误判为 "object"。


2. instanceof:判断对象归属

instanceof 用于判断一个对象是否属于某个构造函数的实例。它的判断机制是:通过对象的隐式原型链(__proto__)查找是否存在等于右边构造函数的 prototype

console.log([] instanceof Array);      // true
console.log({} instanceof Object);     // true
console.log(function(){} instanceof Function); // true
console.log([] instanceof Object);     // true

image.png

注意:

  • instanceof 只能判断引用类型,不能判断基本类型。
    console.log(123 instanceof Number); // false
    

image.png

  • 适合判断自定义对象、数组、函数等。

3. Object.prototype.toString.call:最精确的类型判断

如果你想要精确判断所有类型,包括 nullundefined,推荐使用 Object.prototype.toString.call()

console.log(Object.prototype.toString.call(123));         // [object Number]
console.log(Object.prototype.toString.call('abc'));       // [object String]
console.log(Object.prototype.toString.call(null));        // [object Null]
console.log(Object.prototype.toString.call(undefined));   // [object Undefined]
console.log(Object.prototype.toString.call([]));          // [object Array]
console.log(Object.prototype.toString.call({}));          // [object Object]
console.log(Object.prototype.toString.call(function(){}));// [object Function]

image.png

原理简述

  • 如果 this value 未定义,则返回 "[object Undefined]"
  • 如果 this value 为 null,则返回 "[object Null]"
  • 其他类型会返回 "[object 类型名]"

这种方式几乎可以判断所有 JS 内置类型,是最推荐的类型判断方法。

注意

返回的结果是一个用 [] 包裹的字符串,所以如果只想要得到类型的话,可以使用方法: console.log(type.slice(8, -1)) 将类型截取出来。

image.png

4. Array.isArray:专门判断数组

判断数组最推荐的方法是 Array.isArray()

console.log(Array.isArray([]));      // true
console.log(Array.isArray({}));      // false
console.log(Array.isArray('abc'));   // false

三、类型转换的原理与场景

类型转换分为显示转换隐式转换,本质原理一致,只是触发方式不同。

1. 显示类型转换

  • 转布尔:Boolean(x)
  • 转数字:Number(x)
  • 转字符串:String(x)

例子:

console.log(Boolean(0));      // false
console.log(Number('123'));   // 123
console.log(String(456));     // "456"

image.png

2. 隐式类型转换

JS 在特定场景下会自动进行类型转换,常见场景有:

  • 四则运算:+ - * / %
  • 判断语句:if while == >= <= != > <

例子:

console.log('5' + 3);   // "53"(字符串拼接)
console.log('5' - 3);   // 2   (字符串转数字)
console.log(1 == '1');  // true(== 会进行类型转换)
console.log([] == false); // true(复杂的隐式转换)

image.png


四、== 与 === 的区别

  • == 会进行隐式类型转换,只判断值是否相等。
  • === 不会进行类型转换,值和类型都要相等。

例子:

console.log(1 == '1');   // true
console.log(1 === '1');  // false
console.log(null == undefined); // true
console.log(null === undefined); // false

建议:
开发中优先使用 ===,避免隐式转换带来的坑。


五、ToPrimitive 原理

当 JS 需要将对象转为原始类型时,会调用 ToPrimitive,分为两种模式:

  • ToPrimitive(obj, String):先调用 toString(),再调用 valueOf()
  • ToPrimitive(obj, Number):先调用 valueOf(),再调用 toString()

例子:

const obj = {
  valueOf() { return 123; },
  toString() { return 'abc'; }
};

console.log(String(obj)); // "abc"(优先 toString)
console.log(Number(obj)); // 123  (优先 valueOf)

image.png 如果 toString()valueOf() 返回的不是原始类型,会继续尝试下一个方法,否则抛出 TypeError。


六、valueOf 和 toString 的区别

  • valueOf():返回对象的原始值,通常用于数字运算。
  • toString():返回对象的字符串表示,通常用于字符串拼接。

例子:

const arr = [1, 2, 3];
console.log(arr.valueOf()); // [1, 2, 3]
console.log(arr.toString()); // "1,2,3"

七、常见隐式类型转换场景

1. 四则运算

  • +:只要有一个是字符串,另一个也会转为字符串拼接。
  • 其他运算符(- * / %):会将操作数都转为数字。

例子:

console.log('2' + 3); // "23"
console.log('2' - 1); // 1
console.log(true + 1); // 2
console.log(false * 2); // 0

2. 判断语句

  • if (x)while (x):会将 x 转为布尔值。

例子:

if ('') console.log('不会执行');
if (0) console.log('不会执行');
if ([]) console.log('会执行'); // 空数组为 true

八、总结

  • 类型判断优先用 Object.prototype.toString.call,判断数组用 Array.isArray

  • 类型转换要分清显示和隐式,开发中尽量避免隐式转换带来的不确定性。

  • ===== 区别牢记,推荐全用 ===

  • 理解 ToPrimitivevalueOftoString 的调用顺序和作用。

  • 多写例子,多调试,遇到类型相关的 bug,先用 console.log(typeof x)Object.prototype.toString.call(x) 检查类型。


类型判断和类型转换是 JS 基础中的基础,掌握好常用方法和转换逻辑,写代码更稳健,排查 bug 更高效。遇到类型相关问题,回头看看这篇,一定有收获!