JavaScript 数据类型基础知识

293 阅读6分钟

一、数据类型

1. 基本数据类型

  • string
  • number:NAN「不是一个有效数字」、Infinity「无穷大的值」

检测是否为有效数字:isNAN([value])

不论[value]啥类型,默认隐式转换为数字类型Number([value]),再校验是否为有效数字,如果是有效数字返回false,不是有效数字返回true。

  • Boolean

  • undefined

  • null

  • symbol (唯一值,ES6新增)

    1)给对象设置唯一值属性

    let key = Symbol()
    let obj = {
          [key]:100
        }
    console.log(obj[key]) 
    
    // 获取当前对象所有symbol类型的私有属性
    Object.getOwnPropertySymbols(obj)
    
    // 获取对象所有非Symbol属性
    Object.keys(obj)
    

    2)Symbol 方法

    Symbol.hasInstance, Symbol.toStringTag, Symbol.toPrimitive

  • bigInt :大数

    最大安全数字:9007199254740991,超过这个数字进行运算就不准确了
    Number.MAX_SAFE_INTEGER
    
    最小安全数字:-9007199254740991
    Number.MIN_SAFE_INTEGER
    

    服务端有longInt长整型,如果传给客户端,客户端无法有效处理,就需要用到bigInt处理

    let num = BigInt('9007199254740991') + 1n // 得到9007199254740992n
    
    服务器不支持bigInt,转为字符串即可
    let newNum = num.toString() 
    

2. 引用数据类型(对象类型)

  • 标准普通对象:object

  • 标准特殊对象:Array/RegExp/Date/Error/Math/ArrayBuffer/DataView/Set/Map...

  • 非标准特殊对象:Number/String/Boolean/Symbol/BigIng...

    1. 字面量方式创建出来的是原始值
       let a = 10
    2. 构造函数/Object 方式创建出来的是对象值
       let b = new Number(10)
       let c = Object(10)
    总结:基于构造函数「或者Object」创建出来的原始值对象类型的格式信息,类型属于对象类型.
    

    SymbolBigInt不能用构造函数方式创建,会报错。 可以使用Object()方式.

    image.png

  • 函数对象,可调用对象「实现了call方法」:function

    • 属于特殊的对象,它拥有很多函数的概念,对象只是它的附属。
    • 每一个函数的原型链直接指向Function的原型(__proto__ => Function.prototype),所以直属类型是函数,所以函数类型应该是一个单独的分类。

二、数据类型检测

1. typeof 检测数据类型的逻辑运算符

1)返回的结果是一个字符串,包含了对应的数据类型

typeof typeof typeof 12 => 'string'

2) 弊端:

  • typeof null => "object"

    typeof 认为存储的二进制中前几位都是0的为object,null存储的结果是000000,返回“object”。但可以理解为这是一个bug,null依然是基本数据类型。

  • typeof 不能细分对象类型(除函数对象返回‘function’,其余返回都是“object”)

  • 检测一个未被声明的变量不会报错,返回‘undefined’

3) 底层处理机制

  • 所有的数据类型值,在计算机底层都是按照“二进制”来存储的「64位」
  • typeof是按照二进制值来检测:前三位是000的,都被认为是对象。如果对象内部实现了[[call]]方法,则认为是函数。
  • typeof处理性能相对好一些

2. instanceof 检测是否为某个类的实例

let n1 = 10 // Number类的一个实例「原始值」
let n2 = new Number(10) //  Number类的一个实例「对象」

// 数字类型为什么可以调方法?内部处理机制“装箱和拆箱”:10->Object(10)「对象实例」
console.log(n1.toFixed(2)) // 10.00
console.log(n2.toFixed(2)) // 10.00

console.log(n1 + 10) // 20
console.log(n2 + 10) // 20 n2对象先找Symbol.toPrimitive,没有再找valueof「原始值」

console.log(n1 intanceof Number) // false instanceof有缺陷,不能识别原始值
console.log(n2 intanceof Number) // true

3. constructor 检测构造函数

4. Object.prototype.toString.call([value]) 检测数据类型

---------------工具类检测方法---------------

5. Array.isArray([value]) 检测是否为数组

6. isNAN 检测是否是一个有效数字

三、特殊数据类型分析

1. Number

  • NAN(not a number)不是一个有效数字

    NAN是特殊的数字类型, console.log(typeof NAN) // "number"

    判断一个值是否是NAN,使用isNAN方法,返回值为false,则值为数字类型。

    isNAN(0) // false
    isNAN('A') //true
    

    其中涉及一个隐式转换,利用Number()方法判断值能否能否转为一个数字,如果不能返回则为NAN。

  • Infiniti/-Infinity: 正无穷大/负无穷大,也属于数字类型。

2. object 普通对象

对象的属性名一定不能是引用类型值,默认会把引用类型值转换为字符串进行处理(toString()方法,转换为:“[object object]”)。属性名可以是数字,布尔值,字符串。

3. 数组

数组是特殊的对象,区别是数组的属性名是有规律的逐渐递增的代表位置的数字索引。

四、数据类型转换规则

1. 把其他类型「原始值」转换为对象

Object([value])

2. 其他类型转为布尔

规则:只有“0,NAN,undefined,null,‘’「空字符串」”会变为false,其余都转为true

转换方法:
  • Boolean([value])
  • !![value]
  • ![value] 转换为布尔类型取反
  • 条件判断:if(1){}
  • A || B 或 A && B 举例: console.log(!![]) => true console.log(!!-1) => true

3. 其他类型转为字符串

规则:原始值转换直接用引号包起来;bigInt会去除n。

转换方法:
  • toString() 「排除Object.prototype.toString(),因为是检测数据类型的」

  • 字符串/模版字符串拼接 「“+”在js中除了数学运算,还有字符串拼接功能」

    “+”左右两边,有一边出现字符串或者部分对象,都是按照字符串拼接处理的

    let n = 10
    {}+n => 10 // 把左侧的{}当作代码块,不参与运算,运算的只有+n
    n+{} // '10[objec object]' 字符串拼接
    

    不是所有对象都是字符串拼接,规则如下:

    • 先去调对象的Symbol.toPrimitive属性值,如果没有这个属性
    • 再去调对象的valueOf 获取原始值,如果不是原始值
    • 再去调对象的toString()转换为字符串。「如果是想转换为数字,则还会调用Number处理」
    1:
    10 + [10,20] => 1010,20
    10 + new Number(10) => 20 //new Number(10).valueOf()有原始值2:
    let obj = {x:10}
    10 + obj = “10[object object]”  
    // obj[Symbol.toPrimitive] -> undefined
    // obj.valueOf() -> {x:10}
    // obj.toString() -> "[object object]"3:
    改写上条示例,让结果变为20
    let obj = {
        x:10,
        // 重写属性
        [Symbol.toPrimitive](hint){
        console.log(hint) // "default","string","number"
          return this.x
        }
    }
    10 + obj = 20
    // hint值是由浏览器,根据词法解析来识别的。
    

4. 其他类型转为数字

  • Number([value])
    • 一般用于隐式转换
    • 字符串 -> 数字 「空字符串变为0,字符串中出现非有效数字字符结果为NAN」
    • 布尔 -> true-1,false-0
    • null -> 0
    • undefined -> NAN
    • symbol -> 报错
    • bigInt -> 正常转换
    • 对象遵循 Symbol.toPrimitive/valueOf/toString/Number
  • parseInt/parseFloat([value])
    • 首先会把[value]变为字符串,从字符串左侧第一个字符开始查找,直到找到一个非有效数字字符为止,把找到的结果转换为数字,一个都没找到,结果就是NAN。「parseFloat多识别一个小数点」

      image.png