Null类型
Null类型同样只有一个值,即特殊值null,逻辑上讲,null值表示一个空指针对象,这也是给typeof传一个null会返回object的原因
let car = null ; console.log(typeof car); // "object"
在定义将来要保存对象值的变量时,建议使用null来初始化,不要使用其他值,这样,只要检查这个变量的值是不是null就可以知道这个变量是否后来被重新赋予了一个对象的引用
if(car != null){ // car是一个对象的引用
undefined值是由null值派生而来,因此EMCA-262将它们定义为表面上相等
console.log(null == undefined) // true
用等于操作符(==)比较null和undefined始终返回true。但要注意,这个操作符会为了比较而转换它的操作数
即使null和undefined有关系,它们的用途也是不一样的,正如前文所述,永远不必显式的将变量值设置成为undefined,但是null不是这样的。任何时候,只要变量需要保存对象,而当时又没有那个对象可保存,我们就需要使用null来填充该变量,这样就可以保持null是空对象指针的语义,并且进一步与undefined分开
null是一个假值,因此如果我们需要,可以用更简洁的方式去检测它,不过我们要记住,也有其他可能的值是假值,所以一定要明确自己想检测的就是null这个字面值,而不仅仅是假值
<script> let message = null ; let age ; if(message){ // 这个块不会被执行 } if(!message){ // 这个块会被执行 } if(age) { //这个块不会被执行 } if(!age){ // 这个块会被执行 } </script>
Boolean类型
Boolean类型是EMCAScript使用最频繁的类型之一,有两个字面值:true和fasle。这两个布尔值不同于数值,因此true不等于1,false不等于0
let found = true ; let lost = false ;
注意注意
布尔值字面量true和false是区分大小写的,因此TRUE和FALSE是有效标识符,但不是布尔值
虽然布尔值只有两个,但所有其他ECMAScript类型的值都有相应的布尔值的等价形式,要将一个其它类型的值转换为布尔值,可以调用特定的Boolean()转型函数
let message = "Hello world"; let messageAsBoolean = Boolean(message);
在这个例子中,字符串message会被转换为布尔值并保存在变量messageAsBoolean中,Boolean() 转型函数可以在任意类型的数据上调用,而且始终返回一个布尔值,什么值能转换为true或者false的规则取决于数据类型和实际的值
数据类型 | 转换为true的值 | 转换为false的值 |
Boolean | TRUE | FALSE |
String | 非空字符串 | “”(空字符串) |
Number | 非零数值 | 0、NAN(参见后面的相关内容) |
Object | 任意对象 | null |
Undefined | N/A | undefined |
理解以上转换十分重要,因为像if等流程控制语句会自动执行其它类型值到布尔值的转换
<script> let message = "Hello World"; if(message){ console.log("Value is true"); } </script>
在这个例子中,console.log会输出字符串Value is true,因为字符串message会被自动转换为等价的布尔值true,由于存在这种自动转换,理解流控制语句中使用的是什么变量就很重要,错误地使用对象而不是布尔值会明显改变应用程序的执行流
Number类型
ECMAScript中最有意思的数据类型或许就是Number,Number类型使用IEEE 754格式表示整数和浮点值(在某些语言中也叫双精度值)。不同的数值类型相应地也有不同的数值字面量格式
最基本的数值字面量格式是十进制整数,直接写出来即可
let intNum = 55 ; // 整数
整数也可以用八进制或十六进制字面量表示,对于八进制字面量,第一个数字必须是0,然后是相应的八进制数字,如果字面量中包含的数字超出了应有的范围,就会忽略前缀的零,后面的数字序列会被当做十进制数
let octalNum1 = 070 ; let octalNum2 = 079 ; let octalNum3 = 08 ;
八进制字面量在严格模式下是无效的,会导致JavaScript引擎抛出语法错误
要创建十六进制字面量,必须让真正的数值前缀为0x(区分大小写),然后是十六进制数字(09以及AF)。十六进制数字中的字母大小写均可
let hexNum1 = 0xA; // 十六进制10 let hexNum2 = 0x1f; // 十六进制31
使用八进制和十六进制格式创建的数值在所有教学操作中都被视为十进制数值
注意
由于JavaScript保存数值的方式,实际上可能存在正零和负零。正零和负零在所有的情况下都被认为是等同的~
浮点值
要定义浮点值,数值中必须包含小数点,而且小数点后面必须至少含有一个数字,虽然小数点前面不是必须要有整数,但是推荐加上
let floatNum1 = 1.1 ; let floatNUM2 = 0.1 ; let floatNum3 = .1 ; // 有效,但不推荐
因为存储浮点值使用的内存空间是存储整数值的两倍,所以ECMAScript总是想方设法地把值转换为整数,在小数点后面没有数字的情况下,数值就会变成整数,类似的,如果数值本身就是整数,只是小数点后面跟着0,那么也会被转换成整数
let floatNum1 = 1. ; // 小数点后面没有数字,当做整数1处理 let floatNum2 = 10.0 ; // 小数点后面是零,当成整数10来处理
对于非常大或者非常小的数字,浮点值可以用科学计数法表示。科学计数法用于表示一个应该乘以10的给定次幂的数值。EMCA中科学计数法的格式要求是一个数值,ECMAScript中科学计数法的格式要求是一个数值后面跟一个大写或者小写的字母e,再加上一个要乘的10的多少次幂
let floatNum = 3.125e7 // 等于31250000
在这个例子中,floatNum等于31250000,只不过科学计数法显示更加简洁。浮点数的精确度最高可达17位小数,但在这种计算中远不如整数精确,例如0.1+0.2得到的不是0.3,而是0.300 000 000 000 000 04,由于这种微小的舍入错误,导致很难测试特定的浮点值
注意
之所以存在这种舍入错误,是因为使用了IEEE 754数值,这种错误并非ECMAScript所独有,其他使用相同格式的语言也有这个问题
值的范围
由于内存的限制,ECMAScript并不支持表示这个世界上所有的数值。ECMAScript可以表示的最小值保存在Number.MIN_VALUE中,这个值在多数浏览器中是5e-324,;可以表示的最大数值保存在Number.MAX_VALUE中,这个值在多数浏览器中是1.797 693 134 862 315 7e+308。如果某个计算得到的数值超出了JavaScript可以表示的范围,那么这个数值会被自动转换成为一个特殊的Infinity(无穷)值,任何无法表示的负数以**-Infinity**(负无穷大)表示,任何无法表示的正数以Infinity(正无穷大)表示
NaN
有个特殊的值叫NaN,意思是不是数值,用于表示要返回数值的操作失败了(并非抛出错误)。比如,用0除任意数值在其他语言中通常都会导致错误,从而中止代码执行,但是在ECMAScript中,0、+0、-0相除会返回NaN
console.log(0/0); // NaN console.log(-0/+0); //NaN
如果分子是非0值,分母是有符号0或者无符号0,则会返回Infinity或者-Infinity;
console.log(5/0); // Infinity console.log(5/-0); // -Infinity
NaN有几个独特的属性。首先,任何设计NaN的操作始终返回NaN,在连续多步计算时这可能是个问题。其次,NaN不等于包括NaN在内的任何值。例如下面的比较操作会返回false;
注意
虽然不常见,但是isNaN() 可以用于测试对象。此时,首先会调用对象的valueOf() 方法,然后再确定返回的值是否可以转换为数值。如果不能,再调用toString() 方法,并且测试其返回值,这通常是ECMAScript内置函数和操作符的工作方式
总结
本篇文章主要为读者介绍了JavaScript中Null及浮点数相关细节,同时介绍了执行流程,让读者在开发时候能够更好的对JavaScript中语言的特性有一定的了解