总结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
、空字符串、null
、undefined
和NaN
)将变为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]"
说明
最可靠的方法,赛高✿✿ヽ(°▽°)ノ✿