likes
comments
collection
share

如何准确判断JavaScript中的数据类型?一文搞定JavaScript数据类型判断技巧

作者站长头像
站长
· 阅读数 42

一、前言

在JavaScript中,我们经常需要判断数据类型以便于正确地处理数据。本文将介绍JavaScript中的数据类型判断技术,包括typeof操作符、instanceof操作符、Object.prototype.toString方法以及ES6新增的一些数据类型判断方法。

二、typeof 操作符

操作符typeof用于判断一个值的数据类型,返回的结果是一个字符串。常见的typeof返回值包括"`number"、"string"、"boolean"、"undefined"、"object"和"function"。

console.log(typeof 'hello');    //输出: string
console.log(typeof('hello'));   //输出: string
console.log(typeof 666);        //输出: number
console.log(typeof(666));       //输出: number
console.log(typeof true);       //输出: boolean
console.log(NaN);               //输出: NaN
console.log(typeof NaN);        //输出: number
console.log(typeof undefined);  //输出: undefined

console.log(typeof new Date()); //输出: object
console.log(typeof null);       //输出: object
console.log(typeof []);         //输出: object
console.log(typeof {});         //输出: object
console.log(typeof function() {});  //输出: function

需要注意的是,typeof null返回的是object而不是nulltypeof能判断除了null之外的所有数据类型。这是一个历史遗留问题,不能用来判断null值。如果要判断null值,可以使用"==="运算符。 typeof判断所有引用类型都是输出object,除了函数function,用typeof判断函数类型输出的是function

三、instanceof 操作符

instanceof操作符用于判断一个对象是否属于某个类(构造函数)的实例。它会检查对象的原型链是否包含构造函数的原型对象。

console.log("hello world" instanceof String)   //false
console.log(new String("hello world") instanceof String) //true
console.log(666 instanceof Number)   //false
console.log(new Number(666) instanceof Number) //true
console.log(true instanceof Boolean) //false
console.log([] instanceof Array)     //true
console.log({} instanceof Object)    //true
console.log(null instanceof null)    //报错
console.log(undefined instanceof undefined) //报错

需要注意的是,instanceof操作符只能判断对象是否属于某个类的实例,无法判断基本数据类型。对一个基本数据类型使用instanceof会返回false,而不会报错,但是我们可以用new关键字来创建它们的实例。 接下来,我们思考一下能不能自己写一个简陋版的instanceof呢?当然可以。

function instance_of (L, R) {
    let left = L.__proto__
    let right = R.prototype
    while (left !== null) {
      if (left === right) return true
      left = left.__proto__
    }
    return false
}
console.log(instance_of([], Array));  //true
console.log(instance_of([], Object)); //true
console.log(instance_of({}, Object)); //true
console.log(instance_of(new Date(), Date)); //true
console.log(instance_of({}, String)); //false
console.log(instance_of([], Number)); //false

实例对象的隐式原型等于构造函数的显示原型,我们顺着原型链一直找原型,直到原型为null

四、Object.prototype.toString 方法

Object.prototype.toString方法可以返回一个对象的数据类型。它比typeofinstanceof更加准确和全面,可以判断基本数据类型和各种对象类型。

console.log(Object.prototype.toString(undefined));    //[object Object]
console.log(Object.prototype.toString(666));          //[object Object]
console.log(Object.prototype.toString.call(undefined))//[object Undefined]
console.log(Object.prototype.toString.call(null));    //[object Null]  
console.log(Object.prototype.toString.call(666));     //[object Number]  
console.log(Object.prototype.toString.call('abc'));   //[object String]  
console.log(Object.prototype.toString.call(NaN));     //[object Number] 
console.log(Object.prototype.toString.call([1,2,3])); //[object Array] 
console.log(Object.prototype.toString.call({a:1,b:2}))//[object Object] 
console.log(Object.prototype.toString.call(function(){}))//[object Function] 
console.log(Object.prototype.toString.call(new Date()))//[object Date]
console.log(Object.prototype.toString.call(arguments)) //[object Arguments]

需要注意的是,如果不加上call,就会输出[object Object],加上后才能准确判断。我们仔细观察一下,发现输出的结果中并不全是我们需要的信息,我们似乎只需要后半部分。那么怎样只输出后半部分呢?

Object.prototype.toString(undefined).slice(8,-1)       //Object
Object.prototype.toString(666).slice(8,-1)             //Object
Object.prototype.toString({}).slice(8,-1)              //Object
Object.prototype.toString.call(undefined).slice(8,-1)  //Undefined
Object.prototype.toString.call(null).slice(8,-1)       //Null
Object.prototype.toString.call(666).slice(8,-1)        //Number
Object.prototype.toString.call('abc').slice(8,-1)      //String 
Object.prototype.toString.call(NaN).slice(8,-1)        //Number
Object.prototype.toString.call([1,2,3]).slice(8,-1)    //Array
Object.prototype.toString.call({a:1,b:2}).slice(8,-1)  //Object
Object.prototype.toString.call(function () {}).slice(8,-1) //Function
Object.prototype.toString.call(new Date()).slice(8,-1) //Date

因代码过长不便展示,请各位自行加上console.log()。前半部分的[object是固定的,后半部分长度不固定,所以我们这里采用slice(8,-1)8表示从第八位开始截取,不包括第八位,-1表示从右往左数除掉一位,也就是去掉右中括号。

五、ES6 新增的数据类型判断方法

ES6新增了一些数据类型判断方法,包括Number.isNaNNumber.isFiniteArray.isArrayObject.is等方法。

1. Number.isNaN

Number.isNaN方法用于判断一个值是否为NaN,它比全局的isNaN方法更加严格,只有在值为NaN时返回true,其他情况都返回false

console.log(Number.isNaN(NaN));          //true
console.log(Number.isNaN(42));           //false
console.log(Number.isNaN("hello world"));//false
console.log(Number.isNaN(undefined));    //false
console.log(Number.isNaN(null));         //false

2. Number.isFinite

Number.isFinite方法用于判断一个值是否为有限数值,它在值为Infinity-InfinityNaN时返回false,其他情况都返回trueNumber.isFinite只能判断数值类型的数据是否为有限数值,对于其他数据类型返回都是false

console.log(Number.isFinite(0));            //true
console.log(Number.isFinite(-16));          //true
console.log(Number.isFinite(42));           //true
console.log(Number.isFinite(Infinity));     //false
console.log(Number.isFinite(-Infinity));    //false
console.log(Number.isFinite(NaN));          //false
console.log(Number.isFinite("hello world"));//false
console.log(Number.isFinite(undefined));    //false
console.log(Number.isFinite(null));         //false
console.log(Number.isFinite(true));         //false

3. Array.isArray

Array.isArray方法用于判断一个值是否为数组类型。

console.log(Array.isArray([]));           //true
console.log(Array.isArray([1, 2, 3]));    //true
console.log(Array.isArray({}));           //false
console.log(Array.isArray("hello world"));//false
console.log(Array.isArray(undefined));    //false
console.log(Array.isArray(null));         //false

4. Object.is

Object.is方法用于比较两个值是否相等,它比全局的===运算符更加严格,可以判断NaN值和-0+0的差别,使用Object.is方法能够更加准确地比较两个值是否相等。

console.log(Object.is(42, 42));     //true
console.log(Object.is("hello world", "hello world"));//true
console.log(Object.is(NaN, NaN));   //true
console.log(Object.is(+0, -0));     //false
console.log(Object.is('666', 666)); //false
console.log(Object.is(true, 1));    //false
console.log(Object.is(true, 'true')); //false

六、NaN 和 "== 、==="

在实际编写JavaScript程序时,需要注意一些细节问题,以避免出现不必要的错误或者行为不符合预期的情况。以下是一些常见的问题和解决方法。

1. NaN

NaNNot A Number的缩写,NaN不是一种数据类型,它属于number类型,NaN是一个特殊的值,与任何值都不相等,包括它自己。因此,判断一个值是否为NaN需要使用isNaN()函数。

2. ==(两个等号)和 ===(三个等号)

在JavaScript中,=====都是用来比较两个值是否相等的运算符。它们的主要区别在于比较的严格程度和类型转换的方式。 ==(相等运算符):在进行比较时会进行类型转换,如果两个值的类型不同,会将它们转换为相同的类型再进行比较。 ===(严格相等运算符):在进行比较时不会进行类型转换,如果两个值的类型不同,直接返回false。

console.log(1 == "1");          //true
console.log(1 === "1");         //false
console.log(0 == false);        //true
console.log(0 === false);       //false
console.log(null == undefined); //true,
console.log(null === undefined);//false

因为nullundefined都是JavaScript中的特殊值,使用==时被认为是相等的。

需要注意的是,由于==会进行类型转换,因此可能会出现一些奇怪的结果。

console.log(null == 0); //false,null会被转换为数字0
console.log(null < 1);  //true,null会被转换为数字0
console.log("5" == 5);  //true,字符串"5"会被转换为数字5
console.log(true == 1); //true,true会被转换为数字1

需要注意,虽然null会被转成数字0,但是null == 0仍然输出false。 因此,在比较两个值时,建议使用===,这样可以避免由于类型转换等原因导致的错误比较。

七、总结

本文介绍了JavaScript中常见的数据类型判断方法,包括typeof操作符、instanceof操作符、Object.prototype.toString方法以及ES6新增的数据类型判断方法。通过这些技术,我们可以准确地判断数据类型,从而正确地处理数据。需要根据具体情况选择合适的方法来判断数据类型,以便于代码的可读性和可维护性。

感谢你阅读这篇文章,如果你觉得写得还行的话,不要忘记点赞、评论、收藏哦!能力一般,水平有限,如有问题欢迎指正,祝生活愉快!

转载自:https://juejin.cn/post/7228933966258683961
评论
请登录