总结JS数据类型中容易混淆的小细节~

前话

数据在内存中的位置

数据存在内存的Stack栈区和Heap堆区,Stack栈区中每个数据顺序存放,Heap区中每个数据随机存放。

数据分为两种:对象和非对象,对象存在Heap堆区,非对象存在Stack栈区。

字符的存储

字符

JavaScript中字符串是使用类似UTF-8形式存储的(USC-2)。

UTF-8 是 Unicode 一种存储规则,也叫字符编码规则。Unicode万国码是一种所有符号的编码,可以容纳各个国家的字符,但是每个字符要用三个以上的字节,太耗费空间去存储。UTF-8 是 Unicode 的实现方式之一,UTF-8最少可用8位存一个字符。

简单数据类型

JavaScript有七种简单数据类型(primitive type):字符串(string)、数字(number)、布尔值(boolean)、undefined、null(Symbol、BigInt为ES6新增的数据类型),记忆口诀:四基两空两新

String

let a = '你好'
let a = "你好,'hello'"
let a = `你好
         hello`

字符串就是零个或多个排在一起的字符,放在单引号、双引号或反引号之中。单引号字符串的内部,可以使用双引号。双引号字符串的内部,可以使用单引号。想保留空格和换行使用反引号。

反斜杠(\)用来表示一些特殊字符,称为转义符,如\n 是换行符。

属性

字符串可以被视为字符数组,所以有length属性,可以使用数组下标来访问某个字符,a[index] ,index的范围0~length-1,a[index]不会报错,会返回undefined。

Number

JavaScript中数字是不区分整数值与浮点数值的,在JavaScript中所有的数均使用64位(8字节)的浮点数格式来存储和表示(IEEE 754标准)。所以数值最大是:±1.7976931348623157 X 10^308,最小是±5X10^-324,可以表示的整数范围是-9 007 199 254 740 992 ~ 9 007 199 254 740 992 (对应的是-2^53~2^53)包含边界值。 当任何数字在进行位运算时 js 内部hui将其转换成32位有符号整型。

由于浮点数不是精确的值,所以涉及小数的比较和运算要特别小心。

  • 符号占1 位,0表示正数,1表示负数
  • 指数占11 位(-1023 ~1024 )
  • 有效数字占52 位( 开头的1省略)

特殊值

  • 正零和负零

    一般情况下都当作0使用,只有+0或-0当作分母,返回的值是不相等的

  • NaN

    表示“非数字”(Not a Number),主要出现在将字符串解析成数字出错的场合。但它的数据类型依然属于Number。NaN === NaN // false

  • Infinity

    Infinity表示正的无穷,-Infinity表示负的无穷。

Boolean

布尔表示一个逻辑实体,可以有两个值:true 和 false。

falsy

一定要记住五个falsy值!!!相当于false但又不是false的值,JS会将falsy值自动转为false,其他值都视为true。

  • null
  • undefined
  • 0
  • NaN
  • ''

Null

null是一个表示“空”的对象,转为数值时为0;null 是表示缺少的标识,指示变量未指向任何对象。可以把 null 作为尚未创建的对象。

  • 在 API 中,null 常在返回类型应是一个对象,但没有关联的值的地方使用。
  • 作为函数的参数, 表示该函数的参数不是对象。
  • 作为对象原型链的终点

Undefined

undefined是一个表示"此处无定义"的原始值,转为数值时为NaN。

  • 一个没有被赋值的变量的类型是undefined。如果方法或者是语句中操作的变量没有被赋值,则会返回undefined。
  • 一个函数如果没有使用return语句指定返回值,就会返回一个undefined值。

区别

  • undefined 是默认的空, null是主动的空
  • 习惯上, 把非对象的空值写为undefined,把对象的空值写为null

Symbol

每个从Symbol()返回的symbol值都是唯一的。一个symbol值能作为对象属性的唯一标识符,防止对象属性冲突发生,这是该数据类型仅有的目的。

使用

👉参考博客:JS 中的 Symbol 是什么?

BigInt

BigInt 可以表示任意大的整数,它提供了一种方法来表示大于 253 - 1 的整数。

使用

  • 在一个整数字面量后面加 n 的方式定义一个 BigInt

  • 调用函数BigInt()

    const theBiggestInt = 9007199254740991n;
      
    const alsoHuge = BigInt(9007199254740991);
    // ↪ 9007199254740991n
    

复杂数据类型

对象则称为合成类型(complex type)的值,因为一个对象往往是多个原始类型的值的合成,可以看作是一个存放各种值的容器。

Object

👉另外一篇博客中有详细总结:JS对象基本用法

数据类型转换

字符串转换

  • 显式地调用 String(value) 来将 value 转换为字符串类型
  • value+""(加上空字符串)

数字型转换

  • 在算术函数和表达式中,会自动进行 number 类型转换 如:value-0
  • Number(value) 显式地将这个 value 转换为 number 类型
  • parseInt(value)parseFloat(value)将这个 value 转换为 number 类型

布尔型转换

  • falsy(如 0、空字符串、nullundefinedNaN)将变为 false
  • 其他值变成 true

注意

  • undefined转为数值时为NaN,null转为数值时为0
  • "0" 和只有空格的字符串(比如:" ")进行布尔型转换时,输出结果为 true

数据类型判断

typeof

使用

typeof 数据

说明

  • typeof可以判断基本类型和函数:Number,String,Boolean,Undefined,symbol,BigInt,Function
  • 无法判断Null,会返回Object
  • 无法判断某个对象的具体类型,对于对象除了函数都会返回Object,比如数组类型会直接返回Object

instanceof

instanceof操作符判断左操作数对象的原型链上是否有右边这个构造函数的prototype属性,也就是说判定对象是否是某个构造函数的实例,最后返回布尔值。

使用

let a=[]
a instanceof Array //true
a instanceof Object;  // true

说明

  • instanceof运算符用于判断对象的具体类型,不能判断7种基本类型的值。
  • 上例可得:a.__proto__ === Array.prototype
  • Array 构造函数是继承自 Object 对象的,因此在 arr 变量上是可以访问到 Object 的 prototype 属性的,Object 构造函数的 prototype 属性存在与 arr 这个数组实例的原型链上,所以a也能判断为Object。

constructor

使用

let a=[]
a.constructor === Array //true

说明

  • 使用constructor判断变量类型的方法,非常高效

  • 但是无法检测 null 或者 undefined 类型,null 和 undefined 根本就没有 constructor 属性

  • 并且constructor 属性易变,不可信赖,这个主要体现在自定义对象上,当开发者重写prototype后,原有的constructor会丢失。

    **ps:**所以,重写对象原型时一般都需要重新给constructor赋值,以保证实例对象的类型不被改写。

    Array.prototype = {
        constructor: Array, 
        name: 'moji',
    };
    var a = new Array();
    a.constructor === Array; // true
    

Object.prototype.toString.call()

使用

Object.prototype.toString.call(null);  //  "[object Null]"

Object.prototype.toString.call([]);  //  "[object Array]"

说明

最可靠的方法,赛高✿✿ヽ(°▽°)ノ✿

参考

判断类型

学习网站

阮一峰教程