JavaScript 类型冷知识

这里整理一些 JavaScript 中类型的一些冷知识~

为什么有的编程规范要求用 void 0 代替 undefined?

这是因为 JavaScript 的一大设计失误 —— undefined 是变量而非关键字,所以它可以被篡改。不理解的话可以看下图:

undefined and void

可以看到 undefined 被修改后返回了 4,明显被篡改了。
而表达式 void 没有返回值,因此返回结果是 undefined 。 void 并不改变表达式的结果,
只是让表达式不返回值。
所以,为了防止被篡改这种行为,有些规范要求使用 void 来替代返回 undefined 的行为。

字符串有最大长度吗?

字符串是有最大长度的,长度为 2^53 - 1 位。值得注意的是这里的长度是指 UTF16 编码字符(有些特殊字符串会占用两个字符,在 ES6 中添加了对这些特殊字符的处理方法)。

那些特殊的数字

Number 对象上的特殊数值

  • Number.EPSILON 属性表示 1 与Number可表示的大于 1 的最小的浮点数之间的差值。
  • Number.MAX_SAFE_INTEGER 常量表示在 JavaScript 中最大的安全整数(maxinum safe integer)(253 - 1)。
  • Number.MAX_VALUE 属性表示在 JavaScript 里所能表示的最大数值。
  • Number.MIN_SAFE_INTEGER 代表在 JavaScript中最小的安全的integer型数字 (-(253 - 1)).
  • Number.MIN_VALUE 属性表示在 JavaScript 中所能表示的最小的正值。
  • Number.NEGATIVE_INFINITY 属性表示负无穷大。
  • Number.NaN 表示“非数字”(Not-A-Number)。和 NaN 相同。
  • Number.POSITIVE_INFINITY 属性表示正无穷大。

Infinity 和 -Infinity

Infinity 表示无穷值,其实就是 Number.NEGATIVE_INFINITY。反正,负无穷大是 -Infinity,即 Number.NEGATIVE_INFINITY。

var a = 1 / 0; // Infinity
var b = -1 / 0; // -Infinity

任何值除以 0 就等于(-)Infinity。

NaN

NaN 意指“不是一个数字”(not a number),但它却是数字类型。怎么样的代码会出现 NaN 呢?

var a = 2 / "foo"; // NaN
typeof a === "number"; // true

注意 NaN 是一个非自反的值,即自身不相等 。

NaN == NaN // false

为了解决检测 NaN 的问题,可以使用 ES6 提供的 Number.isNaN() 方法。

+0 和 -0

在 JavaScript 中存在 -0 这种表达方式:

var a = -1 * 0 // -0
var b = 1 * 0 // 0

要注意将值为 -0 的变量转换为字符串后结果为 "0"
-0 可以用来做数字符号位、行为移动方向等方面起到一定的作用。

为什么在 JavaScript 里 0.1 + 0.2 不等于 0.3?

0.1 + 0.2 == 0.3 // false

因为 JavaScript 中使用的是二进制浮点数,二进制浮点数中的 0.1 和 0.2 并不是十分精确,它们相加的结果并非刚好等于
0.3 ,而是一个比较接近的数字 0.30000000000000004 ,所以条件判断结果为 false 。

消除误差的方式如下:

var n1 = 0.1 + 0.2
var n2 = 0.3
Math.abs( n1 - n2 ) < Number.EPSILON; // true

上文中我们提到了 Number.EPSILON 表示 1 与Number可表示的大于 1 的最小的浮点数之间的差值
。所以只要两个值相减的绝对值结果小于差值就算相等。

什么是基本类型的装箱和拆箱?

装箱

基本类型的装箱我在之前已经提起过了,其实就是在基本类型使用一些方法时会使用相应的装箱对象的 prototype 中的方法。具体来说就是 JavaScript 会零时为变量包装一个装箱对象。

var a = "abc";
a.length; // 3
a.toUpperCase(); // "ABC"

当字符串 a 使用属性和方法时,JavaScript 零时创建了一个 new String('123') 对象并调用这个对象上的属性和方法。

注意:基本类型变量会在调用属性和方法时会零时创建装箱对象,这些变量还是基本类型的。而创建装箱对象创建的则是一个对象。

JavaScript 类型冷知识_第1张图片
基本类型和装箱对象

拆箱

既然基本类型能够自动装箱成为装箱对象,那么装箱对象如何转为基本类型呢?
简单!使用 valueOf() 方法:

var a = new String( "abc" );
var b = new Number( 42 );
var c = new Boolean( true );

a.valueOf(); // "abc"
b.valueOf(); // 42
c.valueOf(); // tru

其实还可以使用强制类型转换的方式进行拆箱。

强制类型转换都哪些?

这里贴一张 JavaScript 中强制类型转换的关系图,讲的很详细:

JavaScript 类型冷知识_第2张图片
类型转换关系图

下面归纳几点类型转换的知识点:

  • JSON.stringify() 方法在强制转换成字符串的时候很好用。
  • 强制类型转换成 number 类型的时候要注意进制问题。
  • 直接使用装箱函数 String、Number 和 Boolean 可以进行强制类型转换,这种转换方式也被叫做显式类型转换。
  • 使用字符串拼接的方式可以强制类型转换为字符串,这种转换方式也被叫做隐式类型转换。
  • 使用 !!value 可以强制类型转换为布尔类型。
  • parseInt、parseFloat 方法可以将 string 转换为 number 类型。

参考资料

  • 极客时间专栏 —— 《重学前端》
  • 《你不知道的 JavaScript (中)》

最后

这些冷知识虽然用的不多,但是也能帮我们更好的理解和使用 JavaScript 类型相关的知识~

你可能感兴趣的