判断js中的数据类型的几种方法

一、概述

判断js中的数据类型有一下几种方法:typeof、instanceof、 constructor、Object.prototype.toString。这篇文章来分析一下这几种方式底层原理,比较一下他们的区别。

二、typeof

typeof 是最常用的判断数据类型的方法,我们可以利用 typeof 来判断number, string, object, boolean, function, undefined, symbol 这七种类型。

底层原理: js 在底层存储变量的时候,会在变量的机器码的低位1-3位存储其类型信息,而typeof运算符就是通过一个存储变量的低位来判断数据类型的。

【注意】:

  1. 系统返回时返回的是相关类型的字符串,在作为判断条件的时候需要额外注意。
  2. 对于null使用typeof运算符,将会返回object。这个由于系统底层实现时,将null的机器码指定为全0,这样设置与对象数据类型的低位完全相同,导致typeof出现了误判。
  3. typeof并不是完全安全的运算符,在使用typeof运算符时,如果出现了暂时性死区,typeof运算符也会导致报错。
  4. 对于使用new构造函数,构造的基本数据类型,将被认定为对象。

实例:

// Numbers
typeof 37 === 'number';
typeof 3.14 === 'number';
typeof(42) === 'number';
typeof Math.LN2 === 'number';
typeof Infinity === 'number';
typeof NaN === 'number'; // Despite being "Not-A-Number"
typeof Number('1') === 'number'; // Number tries to parse things into numbers


// Strings
typeof '' === 'string';
typeof 'bla' === 'string';
typeof `template literal` === 'string';
typeof '1' === 'string'; // note that a number within a string is still typeof string
typeof (typeof 1) === 'string'; // typeof always returns a string
typeof String(1) === 'string'; // String converts anything into a string, safer than toString


// Booleans
typeof true === 'boolean';
typeof false === 'boolean';
typeof Boolean(1) === 'boolean'; // Boolean() will convert values based on if they're truthy or falsy
typeof !!(1) === 'boolean'; 
// two calls of the ! (logical NOT) operator are equivalent to Boolean()


// Symbols
typeof Symbol() === 'symbol'
typeof Symbol('foo') === 'symbol'
typeof Symbol.iterator === 'symbol'


// Undefined
typeof undefined === 'undefined';
typeof declaredButUndefinedVariable === 'undefined';
typeof undeclaredVariable === 'undefined'; 


// Objects
typeof {a: 1} === 'object';

// use Array.isArray or Object.prototype.toString.call
// to differentiate regular objects from arrays
typeof [1, 2, 4] === 'object';

typeof new Date() === 'object';
typeof /regex/ === 'object'; 
// See Regular expressions section for historical results


// The following are confusing, dangerous, and wasteful. Avoid them.
typeof new Boolean(true) === 'object'; 
typeof new Number(1) === 'object'; 
typeof new String('abc') === 'object';


// Functions
typeof function() {} === 'function';
typeof class C {} === 'function';
typeof Math.sin === 'function';

【注意】:

  1. Infinity,NaN会被判断成number
  2. 对于使用两次取反符合的变量,将会被判定为boolean

三、instanceof

其实 instanceof 主要的作用就是测试,是否某个构造函数的属性出现在对象的原型链中的任何位置。

底层原理: 只要右边变量的 prototype 在左边变量的原型链上即可。因此,instanceof 在查找的过程中会遍历左边变量的原型链,直到找到右边变量的 prototype,如果查找失败,则会返回 false

【注意】:

  1. 需要判断的数据应该是对象,其他基本数据类型使用将返回false
  2. 使用new操作符,创建的对象,也可以进行判断
  3. 使用时注意大小写,系统构造函数的首字母都是大写
var newStr    = new String('String created with constructor');
newStr  instanceof String; // returns true
newStr  instanceof Object; // returns true

function Car(make, model, year) {
  this.make = make;
  this.model = model;
  this.year = year;
}
var mycar = new Car('Honda', 'Accord', 1998);
mycar instanceof Car;    // returns true
mycar instanceof Object; // returns true

if (!(mycar instanceof Car)) {
  // Do something, like mycar = new Car(mycar)
}

【注意】:

  1. 使用instanceof判断数据不是特定构造函数的实例时,要添加括号。否则取反符合将和实例结合。

四、constructor

既然可以通过原型来判断数据类型,当然也可以使用变量上的constructor属性来判读具体数据类型。

var a = 5;
a.constructor == Number -----------> true;
var a = "123";
a.constructor == String -----------> true;

function A(){};
function B(){};
A.prototype = new B(); //A继承自B
var aObj = new A();
alert(aobj.constructor === B) -----------> true;
alert(aobj.constructor === A) -----------> false;

【注意】:

  1. 这种方法有一个很大缺陷,就是只能判断直接继承,不同判读间接继承
  2. 判断undefined,null时会报错

五、Object.prototype.toString

通过使用object原型toString方法打印队形类型。

var obj = {a:5};
Object.prototype.toString.call(obj);

问题: 同样是检测对象obj调用toString方法,obj.toString()的结果和Object.prototype.toString.call(obj)的结果不一样,这是为什么?

​ 这是因为toString为Object的原型方法,而Array 、Function等类型作为Object的实例,都重写了toString方法。不同的对象类型调用toString方法时,根据原型链的知识,调用的是对应的重写之后的toString方法(Function类型返回内容为函数体的字符串,Array类型返回元素组成的字符串…),而不会去调用Object上原型toString方法(返回对象的具体类型),所以采用obj.toString()不能得到其对象类型,只能将obj转换为字符串类型;因此,在想要得到对象的具体类型时,应该调用Object上原型toString方法。

【注意】:

  1. 通用方法,可以检测各种类型
  2. 但对于自建的自定义函数,将只能识别为object
  3. 在判定时,要严格依照输出字符串(’[object String]‘)进行判定
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值