NaN
NaN是Not a Number的缩写,意即不是一个数字,但是仍然是Number类型。
在JS中求值运算、类型转换等情况下如果遇到无法执行的代码,就会抛出NaN,例如
console.log(0 / 0); // NaN
NaN的特点:
- 任何与NaN有关的运算都会返回NaN
- NaN和任何值都不相等,包括NaN,即
console.log(NaN === NaN); // false
isNaN()和Number.isNaN()
JavaScript提供了isNaN()全局函数来检测NaN,该函数会对传入的非数值参数尝试进行数值转换,如果可以成功转换则返回false,否则返回true。
console.log(isNaN(124)); // false
console.log(isNaN(false)); // false
console.log(isNaN('345')); // false
console.log(isNaN('hello')); // true
console.log(isNaN({})); // true
console.log(isNaN([])); // false
console.log(isNaN(NaN)); // true
而ES6更新的Number.isNaN()则更稳妥:该方法不会隐式转换参数,只有当传入的表达式或变量为NaN时才会返回true。
console.log(Number.isNaN(124)); // false
console.log(Number.isNaN(false)); // false
console.log(Number.isNaN('345')); // false
console.log(Number.isNaN('hello')); // false
console.log(Number.isNaN({})); // false
console.log(Number.isNaN([])); // false
console.log(Number.isNaN(NaN)); // true
使用isNaN还是Number.isNaN取决于你的开发环境,在不兼容ES6的环境下也可以使用以下模拟Number.isNaN的polyfill:
Number.isNaN = Number.isNaN || function(val){
return typeof val === "number" && isNaN(val);
}
转换为数值的4种方式
JavaScript提供了4种将其他类型转换为数值的方法,分别是:
- Number()
- parseInt()
- parseFloat()
- +号操作符
Number()转型函数
Number()转型函数可以将JavaScript中的任意数据类型转换为数值类型。
- 数值类型原样返回
- 布尔类型true会转换为1,false会转换为0
- null会转换为0
- undefined会转换为NaN
- 对象会首先调用valueOf()方法,如果返回的结果仍是对象,则再调用toString()方法。
- 字符串的情况最为特殊,我们详细总结下:
- 如果字符串为空,则会转换为0;
- 如果字符串只包含有效整数或浮点数,则会转化为对应的数值类型,但是会忽略前置0
- 如果字符串包含有效的二进制、八进制或十六进制格式,则会转换为与之对应的十进制整数
- 如果字符串中还有上述情况之外的其他字符,则会返回NaN
来看几个例子:
console.log(Number(124)); // 124
console.log(Number(false)); // 0
console.log(Number('345')); // 345
console.log(Number("")); // 0
console.log(Number('hello')); // NaN
console.log(Number({})); // NaN
console.log(Number([])); // 0
console.log(Number("0b101")); // 5
+号操作符的转换规则和Number()一样,因此不再赘述。
Number()适用于任何数据类型,但是在转换字符串时稍显不足,因此JavaScript提供了专门用于转换字符串的函数:parseInt()和parseFloat(),前者主要用于转换成整数,后者主要用于转换成浮点数。
parseInt()
parseInt()函数用于解析一个字符串,并返回指定基数对应的整数值。其语法格式如下:
parseInt(string, radix);
string 表示要被解析的值,如果该参数不是一个字符串,则会调用toString()方法转换为字符串,而字符串会忽略前面的空白符
radix 表示的是进制转换的基数,数值范围在2-36之间,当不传递该参数时可能会出现意向不到的结果,因此建议始终传入第二个表示基数的参数。
返回值
整数或NaN
parseInt()函数将字符串转换为整数需要注意以下几点:
- 非字符串类型转换为字符串
尽管parseInt()是用于转换字符串的,但是依然可以传入非字符串类型。当传入的值类型不是字符串时会先调用toString()方法或String()函数转换为字符串后再进行转换
console.log(parseInt(0x16, 16)); // 34
console.log(parseInt('0x16', 16)); //22
上面的例子中当我们传入0x16时,因为0x16是Number类型,因此会先调用toString()方法转换为"22",而十六进制的"22"转换成十进制后会变成34。
因此要特别注意传入非字符串时的转换规则。
- 有效的浮点数值格式
parseInt()主要用来转换为整数,因此该函数不能识别字符串中的表示浮点数的e或.(小数点)
console.log(parseInt('2e4')); // 2
console.log(parseInt(5e3)); // 5000
console.log(parseInt('12.7')); // 12
- 空字符串
parseInt()转换时主要看字符串中的有效数字,同时会忽略开头的空白字符,因此空字符串中没有有效数字字符,会返回NaN
console.log(parseInt('')); // NaN
4.普通字符串
对于普通字符串,会从第一位开始寻找有效数值(也可以识别开头的+和-号),直至遇到非有效数值时停止,截取前面的有效数字转为数字。
console.log(parseInt('32blue')); // 32
console.log(parseInt(' -70.1')); // -70
console.log(parseInt('01010')); // 1010,会忽略前面的零
5.可以设置进制转换的基数
如果明确要转换的字符串是有效的二进制、八进制或十六进制,那么可以省略其前缀并设置对应的基数,parseInt会将其转换为对应的十进制形式。
console.log(parseInt('1010', 2)); // 10
console.log(parseInt('1010', 8)); // 520
console.log(parseInt('1010', 10)); // 1010
console.log(parseInt('1010', 16)); // 4112
parseFloat()
parseFloat()主要用来将字符串尽可能转换为浮点数。
parseFloat()没有第二个可选的基数参数,因此相对规则简单点。
parseFloat()也是从字符串的第一位开始寻找有效的浮点数值字符(包括第一个e以及第一个.(小数点)),直至遇到非有效数值时停止,并截取有效字符返回对应的浮点数格式。
console.log(parseFloat("2e2"));
console.log(parseFloat("12.7.1"));
console.log(parseFloat("12blue"));
console.log(parseFloat("false"));
注意:parseFloat()不认识其他进制的前缀,会始终认为其是十进制格式,因此如果传入的值为其他进制的字符串形式,则会返回0
console.log(parseFloat("0b101")); // 0
console.log(parseFloat("0o101")); // 0
console.log(parseFloat("0x101")); // 0
console.log(parseFloat("101")); // 101
Number.parseInt()和Number.parseFloat()
ES6将转换字符串的这两个全局函数挂载到Number对象上作为Number的静态方法来使用,其效果等同于ES5下的全局方法。
console.log(Number.parseInt === parseInt); // true
console.log(Number.parseFloat === parseFloat); // true