2.数据类型的细节知识

237 阅读6分钟

JS中的数据类型(7+2)

  1. 基本数据类型
    1. number
    2. string
    3. boolean
    4. null
    5. undefinrd
    6. symbol
    7. bigint
  2. 引用数据类型
    1. object
      1. 普通对象
      2. 数组对象
      3. 日期对象
      4. 正则对象
      5. Math数学函数对象
      6. .....
    2. function
      为什么要把function单独拎出来呢?function是有对象的特点,但是每个函数的__proto__ (原型链)直接指向的是 Function.prototype

数据类型检测

  1. typeof 检测数据类型的逻辑运算符
  2. instanceof 检测是否为某个类的实例
  3. constructor 检测构造函数
  4. Object.prototype.toString.call 检测数据类型的

JS中数据类型检测,有且只有这4种方案

(当然有一些方法也能检测某些具体的类型,比如说Array.isArray 检测是否是一个数组)

此篇着重介绍typeof,其余三种方案后期再写,链接: JS中四种数据类型检测方案

typeof[value]:
返回当前值的数据类型,它的特点是返回的类型是个字符串 "数据类型",比如"number"...

  1. 因为此时"number" 就是一个字符串而已,所以它的类型就是"string"
  2. typeof的局限性:
    已知null是基本数据类型,但是typeof null 的结果是"object",也可以理解为是js的一个bug
  3. 由此可见,在引用类型中将function单独拎出来是正确的,它的数据类型就是function

typeof总结:

  1. typeof null =>"object"
  2. typeof 不能细分对象类型(检测普通对象或者数组对象等都是"object")

练习题:

let a = typeof typeof typeof [12, 23] // "string"

解析:

  1. 首先要明白一点,多个typeof运算 是从右向左的
  2. typeof [12,23] =》 "object"
  3. typeof "object" =》 "string"
  4. typeof "string" =》 "string"
  5. 注意,一定是字符串string("string"),不是string
  6. 由此可见,2个以及2个以上typeof 结果一定是"string"

Number详解

什么是数字类型?

  1. 0 ,1, -1, 1.2:整数, 正数,负数,0,小数

  2. NaN:不是一个有效数字,但它属于Number类型

  3. Infinity:无穷大

  4. -Infinity: 负无穷大
    验证结果:

    NaN:

    1. NaN和谁都不相等,包括它自己
    2. isNaN(值) 检测这个值是否有有效数字,如果不是有效数字返回TRUE,是有效数字返回FALSE

    练习题:

    let res = parseFloat('left:200px'); // NaN
      if(res === 200) {
        alert(200)
      } else if(res === NaN) {
        alert(NaN)
      } else if(typeof res === 'number') { /
        alert('number')
      } else {
        alert('Invalid Number')
      }
      // 结果是:'number'
    

    解析:

    1. parseFloat([value]):从左到右查找value,如果遇到非有效数字则立即停止查找,本次第一个字符就是非有效数字,所以结果是NaN
    2. NaN和谁都不相等
    3. NaN属于number类型,所以 typeof NaN === 'number' 的结果是true
    4. alert弹出的值,一定是字符串

把其他类型转换为数字的方法

  1. 强转换(基于底层机制转换的) Number([value])
    1. 一些隐式转换都是基于Number完成的(除非自己手动写了[parseInt([value])]/parseFloat([value]),一般情况下都会是用Number)
      1. isNaN('12px') 先把其他类型值转换为数字再检测
      2. 数学运算的时候 :'12px' - 13
      3. 字符串==数字:两个等号比较的时候也是要把其他值转换为数字
      4. ....
  2. 弱转换(基于一些额外的方法转换)
    1. parseInt([value])
    2. parseFloat([value])

练习题:

parseInt("") // 
Number("")
isNaN("")
parseInt(null)
Number(null)
isNaN(nulL)
parseInt('12px')
Number('12px')
isNaN('12px')
parseFloat('1.6PX') + parseInt('1.2PX')+typeof parseInt(null)
isNaN(Number(!!Number(parseInt('0.8'))))
typeof !parseInt(null) + !isNaN(null)

解析:

  1. parseInt 处理的值是字符串,从字符串的左侧开始查找有效数字字符串(遇到非有效数字字符串则停止查找) =》 如果处理的值不是字符串,需要先转换为字符串然后再开始查找
  2. Number 直接调用浏览器最底层的数据类型检测机制来完成
    Number特点:
    1. Number(true) => 1, Number(false) => 0
    2. Number(null) => 0, Number(undefined) => NaN
    3. 字符串必须保证都是有效数字才会转换为数字,否则都是NaN

所以本题答案:

parseInt("") // 从左侧开始查找,没有找到有效数字,结果是:NaN
Number("") // 默认空字符串结果为:0
isNaN("") // 隐形转换。要先把空字符串转化为数字,通过Number转换,Number("")=>0,0是有效数字,所以isNaN(0)的结果是:false
parseInt(null) // parseInt处理的都是字符串。所以先把null转换成字符串'null',null没有toString()方法,所以用的是String(null)=》'null',并没有找到有效数字,所以结果是:NaN
Number(null) // 默认结果是:0
isNaN(nulL) // 隐式转换先调用Number(null)得到0,再isNaN(0),结果是:false
parseInt('12px') // 12
Number('12px') // 只要有一个非有效字符结果就是:NaN
isNaN('12px') // 隐式转换先调用Number('12px')得到NaN,isNaN(NaN)结果是:true
parseFloat('1.61PX') + parseInt('1.2PX') + typeof parseInt(null) //  '2.6number'

1.6 + 1 + typeof NaN => 2.6 + 'number',字符串拼接,所以结果是:'2.6number'
+遇到字符串就是字符串拼接(或者对象,因为对象就是先转换为字符串然后再处理)

isNaN(Number(!!Number(parseInt('0.8'))))
  1. 先算 parseInt("0.8"),结果是0,所以
  2. isNaN(Number(!!Number(0)))
  3. Number(0)的结果还是0
  4. 0 NAN null undefined 空字符串 转换为布尔值是假
  5. 一个!是取反,!0 === true。两个!是取反再取反,所以!true === false
  6. 此时变为 isNaN(Number(false))
  7. Number(false)j结果是:0
  8. isNaN(0)结果是:false
typeof !parseInt(null) + !isNaN(null) // 'booleantrue'
  1. parseInt(null) => parseInt('null') => NaN
  2. !NaN = true (NaN转为布尔类型是0,取反就是true)
  3. typeof true => 'boolan'
  4. isNaN(null) => Number(null)=>0
  5. isNaN(0) => false
  6. !isNaN(0) => true
  7. 'boolan'+true => 'booleantrue'
[] == true  // false 两个等号比较的时候,如果左边是对象,右边是布尔,都转换为数字
Number([]) => Number('') => 0
Number(true) => 1
0和1不相等,所以结果是false

两个等号(==)比较规律:

  1. 对象 == 字符串:对象转化为字符串
  2. null == undefined:除undefined外,null和其他任何值都不相等
  3. NaN和谁(包括自己)都不相等
  4. 剩下的情况都是转为数字再做比较的
let result = 10+flse+undefined+[]+'Tencent'+null+true+{}
console.log(result)
  1. 10+false => 10+0 => 10
  2. 10+undefined = NaN
  3. NaN+[]=>数学运算,要把[]转为数字,转数字前要先转为字符串,[]转为字符串是'',但是还没等将空字符串变为数字时,+就遇到字符串了,直接就是字符串拼接了,所以结果是 => 'NaN'
  4. 'NaN'+'Tencent',也是字符串拼接,剩下的都是字符串拼接了,所以结果是
  5. 'NaNTencentnulltrue'+{}
  6. {}转为字符串是调用toString,结果是:'[object Object]'
  7. 所以最后姐结果是:'NaNTencentnulltrue[object Object]'
!0 // true
![] // false
  1. 0 NAN null undefined 空字符串 转换为布尔值是假
  2. 所以!0结果是:true
  3. []不在第一条之中,所以转为布尔值是true,所以![]结果是:false