JavaScript类型判断机制:typeof、instanceof与Object.prototype.toString详解

作者:代码拾荒

时间:2026-10-30

浏览:92

本文深入解析JavaScript中判断数据类型的三种核心机制:typeof、instanceof以及Object.prototype.toString。通过剖析原型链查找逻辑与[[Class]]属性获取方式,阐明各方法的适用场景与局限性,并结合valueOf隐式转换规则,提供类型检测的最佳实践方案。

文章目录

typeof

typeof 操作符的核心功能是识别数据的基本类型。

类型typeof 结果
基本类型undefinedundefined
Booleanboolean
Numbernumber
Stringstring
Symbolsymbol
BigIntbigint
nullobject
引用类型Object(Object, Array, Map, Set, Regexp, Date 等)object
Functionfunction

当使用 typeof 检测引用类型时,结果通常统一返回 'object'。针对这一局限性,引入了 instanceof 运算符进行补充检测。

instanceof 运算符用于验证构造函数的 prototype 属性是否存在于实例对象的原型链中。

var arr = [];
arr instanceof Array; // true
typeof arr; // "object"
function A() {}
function B() {}
// Javascript 继承
B.prototype = new A();
var b = new B();
b instanceof A; // true
b instanceof B; // true

instanceof 的内部实现原理

  • 核心思路:

基于原型与原型链机制:每个函数拥有显式的 prototype 属性,每个对象拥有隐式原型 __proto__。若对象的原型链中能找到构造函数的显式 prototype,即可判定两者存在关联;

function myInstanceOf(constructor, instance) {
  let prototype = constructor.prototype;
  let proto = instance.__proto__;
  while (true) {
    // 说明道原型链订单, 还未找到, 返回 false
    if (proto === null) {
      return false;
    }
    if (proto === prototype) {
      return true;
    }
    // 继续向 proto 的原型链上遍历
    proto = Object.getPrototypeOf(proto);
  }
}

Object.prototype.toString()

  • toString() 方法返回表示该对象的字符串。该方法旨在重写(自定义)派生类对象的类型转换逻辑。
  • valueOf() 方法返回对象的原始值表示。

该方法由字符串转换优先调用,但数字的强制转换和原始值的强制转换会优先调用 valueOf,因为基本的 valueOf() 方法返回一个对象,toString() 方法通常在结束时调用。

默认情况下(不重写 toString 方法),任何对象调用 Object 原生的 toString 方法,都会返回一个 [object type],其中 type 是对象的类型。

let a = {};
a; // {}
a.toString(); // "[object Object]"

[[class]]

每个实例都有一个 [[Class]] 属性,该属性指定了上述字符串中的 type。[[Class]] 不能直接访问,但通常可以通过 Object.prototype.toString.call(..) 方法调用来展示。

// Boolean 类型,tag 为 "Boolean"
Object.prototype.toString.call(true); // => "[object Boolean]"
// Number 类型,tag 为 "Number"
Object.prototype.toString.call(10); // => "[object Boolean]"
// String 类型,tag 为 "String"
Object.prototype.toString.call("1312312"); // => "[object String]"
// Array 类型,tag 为 "String"
Object.prototype.toString.call([]); // => "[object Array]"
// Function 类型, tag 为 "Function"
Object.prototype.toString.call(function () {}); // => "[object Function]"
// Error 类型(包含子类型),tag 为 "Error"
Object.prototype.toString.call(new Error()); // => "[object Error]"
// RegExp 类型,tag 为 "RegExp"
Object.prototype.toString.call(/\d+/); // => "[object RegExp]"
// Date 类型,tag 为 "Date"
Object.prototype.toString.call(new Date()); // => "[object Date]"
// 其他类型,tag 为 "Object"
Object.prototype.toString.call(new (class {})()); // => "[object Object]"

因此,可以利用此方法来判断每个对象的类型。

function generator(type){
  return function(value){
    return Object.prototype.toString.call(value) === "[object "+ type +"]"
  }
}
let isFunction = generator('Function')
let isArray = generator('Array');
let isDate = generator('Date');
let isRegExp = generator('RegExp');
isArray([]));    // true
isDate(new Date()); // true
isRegExp(/\w/); // true
isFunction(function(){}); //true

以下是一道简单的面试题

+[1 + [2] + 3] + [1 + 2 + true - false] + [[3 - false + "1"]];
// 拆分一下
let a = +[1 + [2] + 3];
// [2]会首先进行转换 [2].valueOf, 结果不是基本类型, [2]在调用toString(), 返回'2', 最后 1 + '2' + 3, 1,3进行隐式转换, +'123' ==> 123
let b = [1 + 2 + true - false];
// [3+true-false], true, false会进行转换, true=>1, false=>0, 最后1-0==>[1+3]==>[4]==>[4].valueOf().toString()==>'4'
let c = [[3 - false + "1"]];
// 先转换数组里面的一层, [3-0+'1']==>['31'], 结果: [['31']]==>[['31']].valueOf().toString()==>'31'
// 最后 a+b+c
// 123+'4'+'31'==>123431

面试题目:如何同时让等式成立 a===1&&a===2&&a===3

思路:

重写 a 的 valueOf 方法

let a = {
  value: [3, 2, 1],
  valueOf: function () {
    return this.value.pop();
  },
};

总结

  • 当一侧为 String 类型,被识别为字符串拼接,并会优先将另一侧转换为字符串类型。
  • 当一侧为 Number 类型,另一侧为原始类型,则将原始类型转换为 Number 类型。
  • 当一侧为 Number 类型,另一侧为引用类型,将引用类型和 Number 类型转换成字符串后拼接。
  • 只有 null undefined '' NaN 0 false 这几个是 false,其他的情况都是 true,比如 {} , []。

以上就是js类型判断内部实现原理示例详解的详细内容,更多关于js类型判断内部原理的资料请关注本站其它相关文章!

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章