三种类型检查方法:typeof、instanceof 和 Object.prototype.toString

天蓬元帅
• 阅读 3797

typeof 运算符

typeof 运算符返回参数的类型。当我们想要分别处理不同类型值的时候,或者想快速进行数据类型检验时,非常有用。
它支持两种语法形式:

  • 作为运算符:typeof x。
  • 函数形式:typeof(x)。

括号有的时候时必须的,如果不加上括号将会因为优先级的问题得不到我们想要的结果。例如:

typeof 'string' === true; // false
typeof ('string' === true); // "boolean"

对 typeof x 的调用会以字符串的形式返回数据类型:

typeof undefined // "undefined"

typeof 0 // "number"

typeof 10n // "bigint"

typeof true // "boolean"

typeof "foo" // "string"

typeof Symbol("id") // "symbol" 

typeof Math // "object"  (1) // 任何其他对象

typeof null // "object"  (2)

typeof alert // "function"  (3) // 函数对象

最后三行可能需要额外的说明:

  1. Math 是一个提供数学运算的内建 object。
  2. typeof null 的结果是 "object"。这是官方承认的 typeof 的行为上的错误,这个问题来自于 JavaScript 语言的早期,并为了兼容性而保留了下来。null 绝对不是一个 object。null 有自己的类型,它是一个特殊值。
  3. typeof alert 的结果是 "function",因为 alert 在 JavaScript 语言中是一个函数。在 JavaScript 语言中没有一个特别的 “function” 类型。函数隶属于 object 类型。但是 typeof 会对函数区分对待,并返回 "function"。这也是来自于 JavaScript 语言早期的问题。从技术上讲,这种行为是不正确的,但在实际编程中却非常方便。

另外 typeof 处理包装类型的时候会返回对应的原始数据类型。但是不推荐这样写。例如:

        typeof Number(1); // "number"
        typeof Boolean(true); // "boolean"
        typeof String('string'); // "string"

typeof 运算符区别对待Object类型和Function类型

从技术角度讲,函数在ECMAScript中是对象,不是一种数据类型。然而,函数也确实有一些特殊的属性,因此通过typeof 运算符来区分函数和其他对象是有必要的。

typeof 运算符对null的处理

这个bug是第一版Javascript留下来的,javascript中不同对象在底层都表示为二进制,而javascript 中每种数据类型使用3bit表示,会把二进制前三位都为0的判断为object类型。

  • 000 表示Object类型的数据。
  • 001 表示Int类型的数据。
  • 010 表示Double类型的数据。
  • 100 表示String类型的数据。
  • 110 表示Boolean类型的数据。

由于null代表空指针,大多数平台中值为0x00,因此null的类型标签就成了0,所以执行typeof时会返回 ‘object’。

instanceof运算符

判断一个变量是数组还是对象

首先我们试着用 typeof 运算符进行测试。

    const arr = [0, 1, 2];
    console.log(typeof arr) // "object"

发现输出结果为"object",这并不是我们期望的结果。
所以使用 typeof 运算符并不能直接判断一个变量时对象还是数组类型。实际上,typeof 运算符在判断基本数据类型时会很有用,但是在判断引用市局类型时,却显得很吃力。

接下来我们试着用 instanceof 运算符进行测试。

instance运算符用于通过查找原型链来检测某个变量是否为某个类型数据的实例。使用instanceof 运算符可以判断一个变量时数组还是对象。

        const a = [0, 1, 2];
        console.log(a instanceof Array); // true
        console.log(a instanceof Object); // true

        const b = {name: 'xx'};
        console.log(b instanceof Array); // false
        console.log(b instanceof Object); // true

有一点需要留意,a 同时还隶属于 Object 类。因为从原型上来讲,Array 是继承自 Object 的。instanceof 在检查中会将原型链考虑在内。
因此我们在判断一个变量时数组还是对象时,应该先判断数组类型,然后再去判断对象类型。如果先判断对象,那么数组值也会被判断为对象类型,这无法满足要求。

我们可以得到以下的封装函数。

        function getDataType (o) {
            if (o instanceof Array) return 'Array'
            if (o instanceof Object) return 'Object'
            return 'others'
        }

另一种思路:判断构造函数

判断一个函数是否时数组或者对象,从另一个角度讲,就是判断变量的构造函数时Array类型还是Ojbect类型。因为一个对象的实例都是通过构造函数生成的,所以,我们可以直接判断一个变量的constructor属性。

        const a = [0, 1, 2];
        console.log(a.constructor === Array); // true
        console.log(a.constructor === Object);  // false

        const b = {name: 'xx'};
        console.log(b.constructor === Array); // false
        console.log(b.constructor === Object); // true

我们可以得到以下的封装函数。

        function getDataType (o) {
            const constructor = o.__proto__.constructor || o.constructor
            if (constructor === Array) return 'Array';
            if (constructor === Object) return 'Object';
            return 'others'
        }

Object.prototype.toString 函数

使用 Object.prototype.toString.call() 方法来揭示类型

每种引用类型都会直接或者间接继承自Object类型,因此它们都包含toString()函数。不同数据类型的toString()类型返回值也不一样,所以通过toString()函数可以准确判断值的类型。

  • 对于 number 类型,结果是 [object Number]
  • 对于 boolean 类型,结果是 [object Boolean]
  • 对于 null:[object Null]
  • 对于 undefined:[object Undefined]
  • 对于数组:[object Array]
  • 对于对象:[object Object]
  • ……等(可自定义)

Symbol.toStringTag

可以使用特殊的对象属性 Symbol.toStringTag 自定义对象的 toString 方法的行为。

let user = {
  [Symbol.toStringTag]: "User"
};
alert( {}.toString.call(user) ); // [object User]

所以,如果我们想要获取内建对象的类型,并希望把该信息以字符串的形式返回,而不只是检查类型的话,我们可以用 {}.toString.call 替代 instanceof。

总结

三种类型检查方法:typeof、instanceof 和 Object.prototype.toString

点赞
收藏
评论区
推荐文章
Karen110 Karen110
3年前
一篇文章带你了解JavaScript类型转换
类型转换是一种将一种数据类型转换为另一种数据类型的方法。一、运算符的类型typeof运算符可以帮助你找到你的变量的类型。typeof运算符返回一个变量或表达式的类型。例:项目JavaScripttypeof运算符typeof运算符返回变量或表达式的类型:document.write(typeof""""typeof"Json"""
美凌格栋栋酱 美凌格栋栋酱
6个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
秃头王路飞 秃头王路飞
3年前
JS数据类型检测
数据类型检测相信大家有的时候判断数据类型的时候会有疑惑1、typeof、instanceof用的话会有哪些缺陷呢?2、哪个api只要记住的话,就可以完美判断呢?1、typeof返回的都是字符串jstypeofSymbol()'symbol'typeofnull'object'typeof'object'typeof'ob
Souleigh ✨ Souleigh ✨
4年前
JS - typeof 与 instanceof
一、typeoftypeof操作符返回一个字符串,表示未经计算的操作数的类型使用方法如下:typeof operandtypeof(operand)operand表示对象或原始值的表达式,其类型将被返回举个例子typeof 1 // 'number'typeof '1' // 'string'
明月 明月
2年前
JS数据类型的几种判断方法
1.typeof(常用)typeof是一个运算符,返回值是一个字符串,用来说明变量的数据类型,可以用来判断number,string,object,boolean,function,undefined,symbol这七种类型.2.instanceof(知道即可)instanceof运算符用于检测构造函数的prototype属性是否出现在某个实例对象的原型链上,返回值为布尔值,用于指示一个变量是否属于某个对象的实例3.Object.prototype.to
Stella981 Stella981
3年前
JavaScript 基础 3
3.标准对象  3.1.概念    typeof操作符获取对象的类型            typeof 123; // 'number'            typeof NaN; // 'number'            typeof 'str'; // 'string'
Wesley13 Wesley13
3年前
mysql中时间比较的实现
MySql中时间比较的实现unix\_timestamp()unix\_timestamp函数可以接受一个参数,也可以不使用参数。它的返回值是一个无符号的整数。不使用参数,它返回自1970年1月1日0时0分0秒到现在所经过的秒数,如果使用参数,参数的类型为时间类型或者时间类型的字符串表示,则是从1970010100:00:0
Stella981 Stella981
3年前
JS中 typeof,instanceof类型检测方式
在js中的类型检测目前我所知道的是三种方式,分别有它们的应用场景:1、typeof:主要用于检测基本类型.typeofundefined;//undefinedtypeof'a';//stringtypeof1;//numbertypeoftrue;//booleanty
Stella981 Stella981
3年前
Python的小括弧,中括号,大括号还有尖括号的区别
在使用python做项目的过程中发现这种语言使用了很多种类型的括号来表达数据类型,常见的有四种,分别是:小括号()、中括号\\和大括号,也叫做花括号{},还有尖括号<,其作用也各不相同,分别用来代表不同的python基本内置数据类型。1、python中的小括号():代表tuple元组数据类型,元组是一种不可变序列。创建方法很简单,大多时候都
Stella981 Stella981
3年前
Javascript中的基本数据类型
Undefined在var或者let中声明了变量但没有赋值时,这个变量的值就是undefined.使用typeof关键字检测未声明变量的类型为undefined.Nullnull表示一个空对象指针,所以用typeof检测null时,会返回objectundefine派生自null,
Stella981 Stella981
3年前
Js——第一课
数据类型:要特别注意相等运算符。JavaScript在设计时,有两种比较运算符:第一种是比较,它会自动转换数据类型再比较,很多时候,会得到非常诡异的结果;第二种是比较,它不会自动转换数据类型,如果数据类型不一致,返回false,如果一致,再比较。由于JavaScript这个设计缺陷,_不要_使用比较,始终