7. JS中的数据类型检测

140 阅读2分钟

1. 有且只有四种方法

1. typeof 运算符
2. instanceof 当前实例是否属于某个类
3. constructor 基于构造函数
4. Object.prototype.toString.call() 最好的js数据检测方法

2. typeof

  1. 基于typeof检测出的结果是一个字符串,字符串中包括对应的类型
  2. 局限:
    1. typeof null => "object" ,null不是对象
    2. 基于 typeof 无法细分出当前值是普通对象还是数组对象,只要是对象,返回的结果都是 `"object"
  3. 打印
  4. typeof题目
console.log(typeof typeof typeof []); // "string"
// => typeof [] => "object"
// => typeof "object" => "string"
// typeof检测结果是字符串,两个及以上同时检测,最终结果 "string"

3. instanceof

console.log("1" instanceof String); // false
console.log(1 instanceof Number); // false
console.log(true instanceof Boolean); // false
// console.log(null instanceof Null);
// console.log(undefined instanceof Undefined);
console.log([] instanceof Array); // true
console.log(function () { } instanceof Function); // true
console.log({} instanceof Object); // true
console.log(/^/ instanceof RegExp); // true

基础数据类型打印false,引用数据类型可以得到正确的结果。 暂且不考虑null和undefined(这两个比较特殊)

  • 通过new关键字去创建基本数据类型,输出true
console.log(new Number(1) instanceof Number); // true
console.log(new Boolean(false) instanceof Boolean); // true
console.log(new String("1") instanceof String); // true
  • null和undefined
console.log(new undefined instanceof undefined)
VM3723:1 Uncaught TypeError: undefined is not a constructor
    at <anonymous>:1:13
(anonymous) @ VM3723:1
console.log(new null instanceof Null)
VM3835:1 Uncaught TypeError: null is not a constructor
    at <anonymous>:1:13
(anonymous) @ VM3835:1

直接报错,null 为js设计败笔。早期准备更改null的类型为null,由于当时已经有大量网站使用了null,如果更改,将导致很多网站的逻辑出现漏洞问题,就没有更改过来,于是一直遗留到现在。

4. constructor

console.log(("1").constructor === String); // true
console.log((1).constructor === Number); // true
console.log((true).constructor === Boolean); // true
//console.log((null).constructor === Null); // 报错
//console.log((undefined).constructor === Undefined); // 报错
console.log(([]).constructor === Array); // true
console.log((function () { }).constructor === Function); // true
console.log(({}).constructor === Object); // true

这里依然抛开null和undefined,constructor似乎完全可以应对基本数据类型和引用数据类型,都能检测出数据类型,事实上并不是如此,来看看为什么:

function Fn(){};
Fn.prototype=new Array();
var f=new Fn();
console.log(f.constructor===Fn); // false
console.log(f.constructor===Array); // true
  • 声明了一个构造函数,并且把它的原型指向了Array的原型,instanceof 检测改变
  • jQuery采用Object.prototype.toString.call()进行数据类型检测的。

5. Object.prototype.toString.call()

var o = Object.prototype.toString;
console.log(o.call("aaa")); // "[object String]"
console.log(o.call(1)); // "[object Number]"
console.log(o.call(true)); // "[object Boolean]"
console.log(o.call(null)); // "[object Null]"
console.log(o.call(undefined)); // "[object Undefined]"
console.log(o.call([])); // "[object Array]"
console.log(o.call(function() {})); // "[object Function]"
console.log(o.call({})); // "[object Object]"
  • 修改原型后,结果不变
function Fn(){};
Fn.prototype=new Array();
console.log(Object.prototype.toString.call(Fn)); // "[object Function]"