1-js判断数据类型

本文最后更新于:2021年2月15日 晚上

某2020前端互助群的每周议题(一)

议题内容引自

1. JavaScript中判断数据类型

首先我来表演个js魔法

typeof null 		   // Object -- null的类型是Object
null instanceof Object // false  -- null不是Object的实例 

精彩!(掌声) 那么,为啥呢?

原因是null不是一个空引用, 而是一个原始值, 参考ECMAScript5.1中文版 4.3.11节; 它只是期望此处将引用一个对象, 注意是”期望”, 参考 null - JavaScript. (引自知乎

既然是原始值,那么,怎么解释typeof null的结果为Object呢,MDN是这么解释的

在 JavaScript 最初的实现中,JavaScript 中的值是由一个表示类型的标签和实际数据值表示的。对象的类型标签是 0。由于 null 代表的是空指针(大多数平台下值为 0x00),因此,null 的类型标签是 0,typeof null 也因此返回 "object"。(参考来源

曾有一个 ECMAScript 的修复提案(通过选择性加入的方式),但被拒绝了。该提案会导致 typeof null === 'null'

魔法结束,聊聊正经的

1. 常见需要判断的数据类型

基本类型:String、Number、Boolean、undefined、null、Symbol(ES6引入)

进阶类型:Function、Array、Object、NaN、空值等

2. 类型判断方案

2.1 typeof

console.log(typeof 'abc'); // "string"
console.log(typeof 123); // "number"
console.log(typeof false); // "boolean"
console.log(typeof undefined); // "undefined"
console.log(typeof null) // "object"
console.log(typeof(Symbol())) // "symbol"
console.log(typeof NaN) // "number"
console.log(typeof []) // "object"
console.log(typeof(function(){})) // "function"

在对nullNaN[]的判断上没有得到理想的结果,typeof无法做到完全区分类型

  • number: 会受到NaN的干扰,很多场景其实判断number类型是想要判断是合理的数字类型
  • null: 历史遗留的bug了
  • 数组会被判别为Object: 这样就无法区分Array和Object了

2.2 Object.prototype.toString()

function varType(obj) {
  return Object.prototype.toString.call(obj)
}
console.log(varType("1")); // "[object String]"
console.log(varType(1)); // "[object Number]"
console.log(varType({})); // "[object Object]"
console.log(varType([])); // "[object Array]"
console.log(varType(function () {})); // "[object Function]"
console.log(varType(null)); // "[object Null]"
console.log(varType(undefined)); // "[object Undefined]"
console.log(varType(true)); // "[object Boolean]"
console.log(varType(NaN)); // "[object Number]"
console.log(varType(Symbol())); // "[object Symbol]"
console.log(varType(RegExp())); // "[object RegExp]"

可见除了NaN以外,其他类型都能判断,以字符串[object <类型>]的格式输出结果

ps:除了使用call()之外,也可以使用apply,唯一的区别是二者接接受的参数格式不同,详见

对NaN的处理可以使用函数isNaN()

console.log(isNaN(NaN))  // true
console.log(isNaN(1))  // false

进行把varType()封装一层如下,这样就可以拿来用了

var isTypeOf = function(type){
    return function(obj){
        return `[object ${type}]` === Object.prototype.toString.call(obj)
    }
}
// 箭头函数形式
var isTypeOf = (type) => (obj) => `[object ${type}]` === Object.prototype.toString.call(obj)

// 测试
console.log(isTypeOf("Array")([])) // true

3. 判断数组

3.1 instanceof

[] instanceof Array看看是否为Array的实例。不过有个坑,instanceof实际上是根据原型链上的继承关系来判断的,而Array继承自Object,因此会有 [] instanceof Object结果为true的情况。

3.2 constructor

通过目标的构造器来判断就不会出现instanceof里的意外结果

[].constructor === Array  // true
[].constructor === Object  // false

3.3 Array.isArray()

Array.isArray([])  // true

3.4 采用前文提及的toString()方法

4. 空值判断

4.1 null:Object.prototype.toString.apply(null) === "[object Null]" (或者用call调用也一样的)

4.2 undefined:typeof undefined === undefined, typeof undefine === null(false,严格比较不会进行数据转换)

**4.3 Array:**先判断是否为数组, 再判断length是否为0。(直接判断length为0不合理,存在类数组

**4.4 Object:**场景不多,群友给出了一个想法 Object.getOwnPropertyNames 判断返回的数组中属性的个数


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!