JavaScript判断数据类型

401 阅读4分钟

前言

和TypeScript相比,js并没有特别严格的数据类型控制,除了存在一些隐式转换外,有时候数据类型的确定在项目中也尤为重要,不然很容易导致一些无关的报错焦头烂额(TypeError),最近项目中也遇到了这个小问题。

本文主要讲的就是数据类型的判断与一些简单的数据转换。

javascript数据类型

1,简单数据类型:String,Number,Boolean,undefined,null,Symbol(es6新增,symbol值能作为对象属性的标识符),BigInt(es11新增,表达表示大于 2^53 - 1 的整数)

2,引用数据类型:Object,可细分为 Array 、Function、RegExp、Date等

数据类型判断

  1. typeof typeof 操作符返回字符串,表示未经计算的操作数的类型(这句话是官方解释),什么意思呢,根据我自己的总结就是

typeof一般用来检验简单数据类型,返回的是基本类型用字符串表示,而复杂数据类型中function返回的是Function,然后其他都返回Object,其中null特殊,表示一个空对象

typeof 1 // 'number'
typeof '1' // 'string'
typeof undefined // 'undefined'
typeof true // 'boolean'
typeof Symbol() // 'symbol'
typeof null // 'object'
typeof [] // 'object'
typeof {} // 'object'
typeof console // 'object'
typeof function(){} // 'function'
  1. instanceof instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上(官方)
object instanceof constructor

因为上述typeof只能检测出简单数据类型,那么复杂数据类型,就一般会配合instanceof来使用,而且instanceof只能检测复杂数据类型,null和undefined会报错

// 定义构造函数
let Person = function() {}
let person = new Person()
person instanceof Person // true
  • 手写实现一个instanceof
function newInstanceOf(leftValue, rightValue) {
  // 判断左右两边值
  if (typeof leftValue !== 'object' || rightValue == null) {
    return false
  }

  const rightProto = rightValue.prototype
  leftValue = leftValue.__proto__

  while (true) {
    if (leftValue === null) return false
    // 找相同类型
    if (leftValue === rightProto) return true
    leftValue = leftValue.__proto__
  }
}
  1. Object.prototype.toString.call() Object.prototype.toString()返回一个表示对象的字符串。

因为对于数字,数组,字符串类型等,他们重写了toString方法,所以我们用Object来进行类型判断,此会根据call方法的this来改变this指向,返回一个[object xxx]这样的字符串,后面表示的就是这个对象的类型。可以理解为用谁就call谁

Object.prototype.toString.call('') // "[object String]"
Object.prototype.toString.call() // "[object Number]"
Object.prototype.toString.call([]) // "[object Array]"
Object.prototype.toString.call(object) // "[object Object]"

var o = new Object();
o.toString(); //  "[object Object]"

JavaScript类型转换

  1. 显示转换
  • Number()
  • String()
  • Boolean()
  • parseInt()
  • toString()

这里就介绍下 parseInt()Number.prototype.toString()

parseInt() 函数

parseInt(string, radix)、

string | 必需。要被解析的字符串。                                                                 
radix  | 可选。表示要解析的数字的基数。该值介于 2 ~ 36 之间。如果省略该参数或其值为 0,则数字将以 10 为基础来解析。如果它以 “0x” 或 “0X” 开头,将以 16 为基数。如果该参数小于 2 或者大于 36,则 parseInt() 将返回 NaN。
parseInt("10");			//返回 10
parseInt("19",10);		//返回 19 (10+9)
parseInt("11",2);		//返回 3 (2+1)
parseInt("17",8);		//返回 15 (8+7)
parseInt("1f",16);		//返回 31 (16+15)
parseInt("010");		//未定:返回 10 或 8
// 如果转换的值是null,undefined,boolean,均转换为NaN
console.log(parseInt('+12.3')) // 12 首位为符号位,其余为为数值,转换为整数
console.log(parseInt('1+2.3')) // 1 符号位出现在其他位置,保留符号位前面的数值
console.log(parseInt('0xa')) // 10
console.log(parseInt('010')) // 10 不解析八进制
console.log(parseInt('123ac')); // 123
console.log(parseInt('0101', 2)) // 5

parseInt() 第二个参数会把第一个参数以第二个参数的进制来解析,返回十进制的值 toString() 会将数值以二进制、八进制、十六进制,乃至其他任意有效进制格式表示

Number.prototype.toString()

NumberObject.toString(radix)
radix | 可选。规定表示数字的基数,使 2 ~ 36 之间的整数。若省略该参数,则使用基数 10。但是要注意,如果该参数是 10 以外的其他值,则 ECMAScript 标准允许实现返回任意值
        指定要用于数字到字符串的转换的基数(从236)。如果未指定 radix 参数,则默认值为 10

一般情况下,调用 toString()方法不必传递参数,但是,在调用数值的 toString()方法时,可以传递一个参数:输出数值的基数。默认情况下,toString()方法以十进制格式返回数值的字符串表示。而通过传递基数,toString()可以输出以二进制、八进制、十六进制,乃至其他任意有效进制格 式表示的字符串值

var num = 10;
console.log(num.toString()) //"10"
console.log(num.toString(2)) //"1010"
console.log(num.toString(8)) //"12"
console.log(num.toString(16)) //"a"

console.log(typeof String(null)) //string

console.log(Number('+12.3')) //12.3
console.log(Number('1+2.3')) // NaN
console.log(Number('123ac')) // NaN
  1. 隐式转换 通常来讲,隐式转换发生在以下 比较运算符(==!=><)、ifwhile 这些需要布尔值地方 和 算术运算(+-*/%) 中
  • 转换为布尔值 undefined, null, false, +0, -0, NaN, "" 都会转换为false,其余为true
  • 转换为字符串 + 运算中,一旦存在字符串,会自动把两边的值转换为字符串
  • 转换为数值 除了+有可能把运算子转为字符串,其他运算符都会把运算子自动转成数值

log

    console.log(Number.prototype.toString()); // "0"
    console.log('+',Boolean(' ')); // + true
    console.log(String('"5"'),'<',String("'10'")); // "5" < '10'
    console.log(String(null),'+','10'); // null + 10
    console.log(Function()); // f anonymous(){}
    console.log(+true) // 1
    console.log("5" < "10") // false
    console.log("bat" > 'bytedance') // false
    console.log(null+10) // 10

    console.log(123['toString'].length + 123); // 124

    ;(function(){
      'use strict';
      fun();
      function fun() {
         console.log('aabb'); // aabb
      }
    })
    
    var a = [1, 2, 3],
    b = [1, 2, 3],
    c = [1, 2, 4];

    console.log(a == b); // false
    console.log(a === b); // false
    console.log(a > c); // false
    console.log(a < c); // true
    console.log("5"+3); // 53
    
    console.log(null === undefined); // false
    console.log(null == undefined); // true
    console.log(!null); // true
    console.log(isNaN(1+null)); // false
    console.log(isNaN(1+undefined)); // true
    console.log(1 == true); // true
    console.log(0 === false); // false
    console.log(1+'1'+false); // 11false
    console.log('2' + ['a',2]); // 2a,2

结语

写的不好,有错误的地方烦请各位大佬多多指教,感恩家人感恩🙏

🚩祝各位一路顺风,顶峰相见