前言
JavaScript它支持多种数据类型。其中,原始数据类型是构建更复杂数据结构的基础。在ES5中,有五种原始数据类型,它们是字符串String、数字Number、布尔值Boolean、未定义Undefined、空值Null。在本篇文章中,作者将带领大家了解这五种数据类型。
数字Number
1. 数字类型
数字分为整数和浮点数。但是在JS中,所有数字都是以64位浮点数的形式被存储,整数也是这样。
1 === 1.0
//true
也就是说JS的底层是没有整数的。当要进行整数运算时,JS会自动把64位浮点数转换成32位整数然后在进行运算。
2.数字精度
根据国际标准 IEEE 754,JavaScript 浮点数的64个二进制位,从最左边开始,是这样组成的。
- 第1位:符号位,
- 第2位到第12位(共11位):指数部分
- 第13位到第64位(共52位):小数部分(即有效数字)
符号位决定了一个数的正负,指数部分决定了数的大小,小数部分决定了数的精度。
指数部分一共有11个二进制位,因此大小范围就是0到2047。IEEE 754 规定,如果指数部分的值在0到2047之间,那么有效数字的第一位默认总是1,不保存在64位浮点数之中。 也就是说,有效数字这时总是1.x...的形式,其中x...的部分保存在64位浮点数之中,最长可能为52位。因此,JavaScript 提供的有效数字最长为53个二进制位。这意味着,绝对值小于2的53次方的整数,即-2^53到2^53,都可以精确表示。
Math.pow(2, 53)
// 9007199254740992
Math.pow(2, 53) + 1
// 9007199254740992
上面代码中,大于2的53次方以后,整数运算的结果开始出现错误。所以,大于2的53次方的数值,都无法保持精度。
2.数字范围
指数部分的长度是11个二进制位,意味着指数部分的最大值是2047(2的11次方减1)。也就是说,64位浮点数的指数部分的值最大为2047,分出一半表示负数,则 JavaScript 能够表示的数值范围为2^1024到2^-1023,超出这个范围的数无法表示。
正向溢出与负向溢出
当一个数大于等于2的1024次方,那么就会发生“正向溢出”,即 JavaScript 无法表示这么大的数,这时就会返回Infinity如果一个数小于等于2的-1075次方(指数部分最小值-1023,再加上小数部分的52位),那么就会发生为“负向溢出”,即 JavaScript 无法表示这么小的数,这时会直接返回0。
Math.pow(2, 1024) // Infinity
Math.pow(2, -1075) // 0
3.特殊的数
JavaScript 提供了几个特殊的数值。
1. +0和-0
前面说过,JavaScript 的64位浮点数之中,有一个二进制位是符号位。这意味着,任何一个数都有一个对应的负值,就连0也不例外。JavaScript 内部实际上存在2个0:一个是+0,一个是-0,区别就是64位浮点数表示法的符号位不同。它们是等价的。
-0 === +0 // true
0 === -0 // true
0 === +0 // true
2. NaN
NaN是 JavaScript 的特殊值,表示“非数字”(Not a Number),主要出现在将字符串解析成数字出错的场合。
1-'a' //NaN
上面代码运行时,会自动将字符串转为数值,但是由于a不是数值,所以最后得到结果为NaN,表示它是“非数字”。
以下是NaN的运算规则。
- NaN不等于任何数
NaN === NaN // false
2.NaN在布尔运算时被当作false。
Boolean(NaN) // false
3.NaN与任何数(包括它自己)的运算,得到的都是NaN。
NaN + 1 // NaN
NaN - 2 // NaN
NaN * 3 // NaN
NaN / 4 // NaN
3.Infinity
Infinity表示“无穷”,用来表示两种场景。一种是一个正的数值太大,或一个负的数值太小,无法表示;另一种是非0数值除以0,得到Infinity。
Math.pow(2, 1024)// Infinity
0 / 0 // NaN
1 / 0 // Infinity
上面代码中,第一个场景是一个表达式的计算结果太大,超出了能够表示的范围,因此返回Infinity。第二个场景是0除以0会得到NaN,而非0数值除以0,会返回Infinity。
Infinity有正负之分,Infinity表示正的无穷,-Infinity表示负的无穷。
Infinity === -Infinity // false
1 / -0 // -Infinity
-1 / -0 // Infinity
Infinity大于一切数值(除了NaN),-Infinity小于一切数值(除了NaN)。
Infinity > 1000 // true
-Infinity < -1000 // true
字符串String
字符串就是零个或多个排在一起的字符,放在单引号或双引号之中。单引号字符串的内部,可以使用双引号。双引号字符串的内部,可以使用单引号。
''
'a'
"a"
'I an "author" '
"I an 'author' "
以上都是合法的字符串
字符串可以被视为字符数组,因此可以使用[],用来返回某个位置的字符,也可以通过length返回字符串的长度
var str = 'hello';
str[0] // "h"
str[1] // "e"
str[4] // "o"
str.length //5
但和数组不同,字符串中的值不能像数组一样修改
布尔值Boolean
布尔值代表“真”和“假”两个状态。“真”用关键字true表示,“假”用关键字false表示。布尔值只有这两个值。
下列运算符会返回布尔值:
- 前置逻辑运算符:
! - 相等运算符:
===,!==,==,!= - 比较运算符:
>,>=,<,<=
如果 JavaScript 预期某个位置应该是布尔值,会将该位置上现有的值自动转为布尔值。转换规则是除了下面六个值被转为false,其他值都视为true。
undefinednullfalse0NaN- 空字符串
空数组([])和空对象({})对应的布尔值,都是true。
if ([]) {
console.log('true');
}
// true
if ({}) {
console.log('true');
}
// true
null 和 undefined
null与undefined都可以表示“没有”
var a = undefined;
var a = null;
上面代码中,变量a分别被赋值为undefined和null,这两种写法的效果几乎等价。
在if语句中,它们都会被自动转为false,相等运算符(==)也会报告两者相等。
if (!undefined) {
console.log('undefined is false');
}
// undefined is false
if (!null) {
console.log('null is false');
}
// null is false
undefined == null
// true
既然含义与用法都差不多,为什么要同时设置两个这样的值?这与历史原因有关。JavaScript 诞生时,最初像 Java 一样,只设置了null表示"无"。根据 C 语言的传统,null可以自动转为0。
Number(null) // 0
5 + null // 5
上面代码中,null转为数字时,自动变成0。
第一版的 JavaScript 里面,null就像在 Java 里一样,被当成一个对象,JavaScript 的设计者Brendan Eich 觉得表示无的值最好不是对象。其次,那时的 JavaScript 不包括错误处理机制,Brendan Eich 觉得,如果null自动转为0,很不容易发现错误。因此,他又设计了一个undefined。区别是这样的:null是一个表示“空”的对象,转为数值时为0;undefined是一个表示"此处无定义"的原始值,转为数值时为NaN。
Number(undefined) // NaN
5 + undefined // NaN
虽然 null 和 undefined 在某些情况下可能看似相似,但它们的用途是略有不同。通常来说,使用 null 来表示一个变量的“空值”,而使用 undefined 来表示变量未定义或对象属性不存在。