JavaScript中的一些特殊数值和方法

时间:2021-07-10 11:23:09

再说数值之前写一些别的小知识点,都是在整理的零碎的东西,不值得单独开一个博客,所以写在一起。

1、一个关于不带大括号的if语句,有意思的小案例,else代码块总是与离自己最近的那个if语句配对。

var m = 1;
var n = 2;

if (m !== 1)
if (n === 2) console.log('hello');
else console.log('world');

上面代码不会有任何输出,else代码块不会得到执行,因为它跟着的是最近的那个if语句,相当于下面这样。

if (m !== 1) {
  if (n === 2) {
    console.log('hello');   
  } else {
    console.log('world');
  }
}

2、关于swicth语句的判定条件是 ‘===’,而不是‘==’。

switch语句后面的表达式,与case语句后面的表示式比较运行结果时,采用的是严格相等运算符(===),而不是相等运算符(==),这意味着比较时不会发生类型转换

var x = 1;

switch (x) {
  case true:
    console.log('x 发生类型转换');
  default:
    console.log('x 没有发生类型转换');
}
// x 没有发生类型转换

由于变量x没有发生类型转换,所以不会执行case true的情况

3、关于javascript中的一些特殊数值

” ” 空字符串对应的布尔值是 false
[ ] { } 空数组和空字符串对应的布尔值是 true
JavaScript 提供Number对象的MAX_VALUE和MIN_VALUE属性,返回可以表示的具体的最大值和最小值。

Number.MAX_VALUE // 1.7976931348623157e+308
Number.MIN_VALUE // 5e-324

下面是关于数字0

数字 1 和数字1.0 在比较中是全等于关系

    1 === 1.0 // true

下面代码中,对0.5连续做25次平方,由于最后结果太接近0,超出了可表示的范围,JavaScript 就直接将其转为0。

var x = 0.5;

for(var i = 0; i < 25; i++) {
  x = x * x;
}

x // 0

JavaScript 内部实际上存在2个0:一个是+0,一个是-0,区别就是64位浮点数表示法的符号位不同。它们是等价的。

-0 === +0 // true
0 === -0 // true
0 === +0 // true

几乎所有场合,正零和负零都会被当作正常的0。

+0 // 0
-0 // 0
(-0).toString() // '0'
(+0).toString() // '0'

唯一有区别的场合是,+0或-0当作分母,返回的值是不相等的。原因是除以正零得到+Infinity,除以负零得到-Infinity,这两者是不相等的。

(1 / +0) === (1 / -0) // false

下面是关于NaN

NaN是 JavaScript 的特殊值,表示“非数字”(Not a Number),主要出现在将字符串解析成数字出错的场合。

5 - 'x' // NaN

上面代码运行时,会自动将字符串x转为数值,但是由于x不是数值,所以最后得到结果为NaN,表示它是“非数字”(NaN)。

0 / 0 // NaN  0除以0也会得到NaNNaN === NaN // false  NaN不等于任何值,包括它本身。
typeof NaN // 'number'

NaN不是独立的数据类型,而是一个特殊数值,它的数据类型依然属于Number,使用typeof运算符可以看得很清楚。

[NaN].indexOf(NaN) // -1

数组的indexOf方法内部使用的是严格相等运算符,所以该方法对NaN不成立。

下面是关于Infinity

Infinity === -Infinity // false

1 / -0 // -Infinity
-1 / -0 // Infinity

Infinity与NaN比较,总是返回false。

Infinity > NaN // false
-Infinity > NaN // false

Infinity < NaN // false
-Infinity < NaN // false

关于Infinity的运算

0 * Infinity // NaN
5 / Infinity // 0
0 / Infinity // 0
null / Infinity // 0
Infinity / 0 // Infinity
Infinity - Infinity // NaN
Infinity / Infinity // NaN
null * Infinity // NaN
Infinity / null // Infinity

Infinity与undefined计算,返回的都是NaN。

undefined + Infinity // NaN
undefined - Infinity // NaN
undefined * Infinity // NaN
undefined / Infinity // NaN
Infinity / undefined // NaN

4、关于数值的一些全局方法

下面关于parseInt

parseInt的转化原理是匹配字符串,所以如果是参数是数字的话他会自先转换成字符串,在进行转换。
例如:

parseInt(1.23) // 1
// 等同于
parseInt('1.23') // 1
parseInt(' 81') // 81 如果字符串头部有空格,空格会被自动去除。

如果字符串的第一个字符不能转化为数字(后面跟着数字的正负号除外),返回NaN。

parseInt('abc') // NaN
parseInt('.3') // NaN
parseInt('') // NaN
parseInt('+') // NaN
parseInt('+1') // 1
parseInt('-1') // -1

所以,parseInt的返回值只有两种可能,要么是一个十进制整数,要么是NaN

对于那些会自动转为科学计数法的数字,parseInt会将科学计数法的表示方法视为字符串,因此导致一些奇怪的结果。如下:

parseInt(1000000000000000000000.5) // 1
// 等同于
parseInt('1e+21') // 1

parseInt(0.0000008) // 8
// 等同于
parseInt('8e-7') // 8

如果第二个参数不是数值,会被自动转为一个整数。这个整数只有在2到36之间,才能得到有意义的结果,超出这个范围,则返回NaN。如果第二个参数是0、undefined和null,则直接忽略。

parseInt('10', 37) // NaN
parseInt('10', 1) // NaN
parseInt('10', 0) // 10
parseInt('10', null) // 10
parseInt('10', undefined) // 10

如果字符串包含对于指定进制无意义的字符,则从最高位开始,只返回可以转换的数值。如果最高位无法转换,则直接返回NaN。

parseInt('1546', 2) // 1
parseInt('546', 2) // NaN

上面代码中,对于二进制来说,1是有意义的字符,5、4、6都是无意义的字符,所以第一行返回1,第二行返回NaN。

如果parseInt的第一个参数不是字符串,会被先转为字符串。这会导致一些令人意外的结果。

parseInt(0x11, 36) // 43
parseInt(0x11, 2) // 1

// 等同于
parseInt(String(0x11), 36)
parseInt(String(0x11), 2)

// 等同于
parseInt('17', 36)
parseInt('17', 2)

上面代码中,十六进制的0x11会被先转为十进制的17,再转为字符串。然后,再用36进制或二进制解读字符串17,最后返回结果43和1。

对于八进制的前缀0,它是字符串还是数字对结果会有不同的影响。
如果是字符串‘011’直接计算parseInt(‘011’, 2) ,011则是会被当作二进制处理,返回3。如果是数字011,则如下计算:

parseInt(011, 2) // NaN

// 等同于
parseInt(String(011), 2)

// 等同于
parseInt(String(9), 2)

下面关于parseFloat()

字符串符合科学计数法,则会进行相应的转换。

parseFloat('314e-2') // 3.14
parseFloat('0.0314E+2') // 3.14

parseFloat方法会自动过滤字符串前导的空格

parseFloat('\t\v\r12.34\n ') // 12.34

如果参数不是字符串,或者字符串的第一个字符不能转化为浮点数,则返回NaN。

parseFloat([]) // NaN
parseFloat('FF2') // NaN
parseFloat('') // NaN
parseFloat(true)  // NaN
parseFloat(null) // NaN
parseFloat('') // NaN
parseFloat('123.45#') // 123.45
Number('123.45#') // NaN

下面是关于isNaN()

isNaN只对数值有效,如果传入其他值,会被先转成数值。比如,传入字符串的时候,字符串会被先转成NaN,所以最后返回true,这一点要特别引起注意。也就是说,isNaN为true的值,有可能不是NaN,而是一个字符串。对于对象和数组,isNaN也返回true。

isNaN('Hello') // true
// 相当于
isNaN(Number('Hello')) // true

isNaN({}) // true
// 等同于
isNaN(Number({})) // true

isNaN(['xzy']) // true
// 等同于
isNaN(Number(['xzy'])) // true

对于空数组和只有一个数值成员的数组,isNaN返回false。之所以返回false,原因是这些数组能被Number函数转成数值。

isNaN([]) // false
isNaN([123]) // false
isNaN(['123']) // false

使用isNaN之前,最好判断一下数据类型。

function myIsNaN(value) {
  return typeof value === 'number' && isNaN(value);
}

判断NaN更可靠的方法是,利用NaN为唯一不等于自身的值的这个特点,进行判断。

function myIsNaN(value) {
  return value !== value;
}

下面关于isFinite(),这个不是很常用

isFinite方法返回一个布尔值,表示某个值是否为正常的数值。这个作为了解就可以。

除了Infinity、-Infinity和NaN这三个值会返回false,isFinite对于其他的数值都会返回true。

isFinite(Infinity) // false
isFinite(-Infinity) // false
isFinite(NaN) // false
isFinite(-1) // true