文章目录
  1. 1. Number类型
    1. 1.1. 整数
    2. 1.2. 浮点值
    3. 1.3. NaN
      1. 1.3.1. 特性:
      2. 1.3.2. 判断NaN的方法 isNaN
    4. 1.4. +0 和 -0
      1. 1.4.1. 产生原因
      2. 1.4.2. 参与运算
      3. 1.4.3. 参与Math对象的方法
      4. 1.4.4. 区分这两个零
    5. 1.5. Infinity
      1. 1.5.1. 正负之分
      2. 1.5.2. 产生原因
      3. 1.5.3. 参与运算
      4. 1.5.4. isFinite函数
  2. 2. 数值转换
    1. 2.1. Number()
    2. 2.2. parseInt()
    3. 2.3. parseFloat()

Number类型

JavaScript内部,所有数字都是以64位浮点数形式储存,即使整数也是如此。所以,1与1.0是相等的,而且1加上1.0得到的还是一个整数,不会像有些语言那样变成小数。

1
2
1 === 1.0 // true
1 + 1.0 // 2

也就是说,在JavaScript语言的底层,根本没有整数,所有数字都是小数(64位浮点数)。容易造成混淆的是,某些运算只有整数才能完成,此时JavaScript会自动把64位浮点数,转成32位整数,然后再进行运算。

由于浮点数不是精确的值,所以涉及小数的比较和运算要特别小心。

1
2
3
4
5
0.1 + 0.2 === 0.3  // false

0.3 / 0.1 // 2.9999999999999996

(0.3 - 0.2) === (0.2 - 0.1) // false

number2.png

解释:根据国际标准IEEE-754,64位浮点数格式的64个二进制位中,第0位到第51位储存有效数字部分(共52位),第52到第62位储存指数部分,第63位是符号位,0表示正数,1表示负数。

1
2
3
4
5
6
7
8
9
Math.pow(2, 53)        // 9007199254740992

Math.pow(2, 53) + 1 // 9007199254740992

Math.pow(2, 53) + 2 // 9007199254740994

Math.pow(2, 53) + 3 // 9007199254740996

Math.pow(2, 53) + 4 // 9007199254740996

从上面示例可以看到,大于2的53次方以后,整数运算的结果开始出现错误。所以,大于等于2的53次方的数值,都无法保持精度。因此,JavaScript提供的有效数字的精度为53个二进制位(IEEE 754规定有效数字第一位默认总是为1,不保存在64位浮点数之中,这一位再加上后面的52位,就是总共53位),也就是说,绝对值小于2的53次方的整数,即-(253-1)到253-1,都可以精确表示。

那么超过253部分的数字怎么处理呢?

1
2
3
Math.pow(2, 53)    // 9007199254740992

9007199254740992111 // 9007199254740992000

上面示例表明,大于2的53次方以后,多出来的有效数字(最后三位的111)都会无法保存,变成0。

另一方面,64位浮点数的指数部分的长度是11个二进制位,意味着指数部分的最大值是2047(2的11次方减1)。也就是说,64位浮点数的指数部分的值最大为2047,分出一半表示负数,则JavaScript能够表示的数值范围为21024到2-1023(开区间),超出这个范围的数无法表示。

如果指数部分等于或超过最大正值1024,JavaScript会返回Infinity(关于Infinity的介绍参见下文),这称为“正向溢出”;如果等于或超过最小负值-1023(即非常接近0),JavaScript会直接把这个数转为0,这称为“负向溢出”。事实上,JavaScript对指数部分的两个极端值(11111111111(二进制)和00000000000(二进制))做了定义,11111111111(二进制)表示NaNInfinity00000000000(二进制)表示0。

1
2
3
4
5
6
var x = 0.5;

for(var i = 0; i < 25; i++) {
x = x * x;
}
console.log(x);// 0

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

  • 精确地描述,Number类型拥有 18437736874454810627(即,264-253+3)个值,表示为 IEEE-754 格式 64 位双精度数值(IEEE 二进制浮点数算术中描述了它)。
  • 除了 IEEE 标准中的 9007199254740990(即,253-2)个明显的“非数字”值;在 ECMAScript 中,它们被表示为一个单独的特殊值:NaN。(请注意,NaN 值由程序表达式 NaN 产生,并假设执行程序不能调整定义的全局变量 NaN,在javascript中NaN是global全局对象的一个属性window.NaN) 在某些实现中,外部代码也许有能力探测出众多非数字值之间的不同,但此类行为依赖于具体实现;对于 ECMAScript 代码而言,NaN 值相互之间无法区别。
  • 还有另外两个特殊值,称为正无穷和负无穷。为简洁起见,在说明目的时,用符号 +∞ 和 -∞ 分别代表它们。(请注意,两个无限数值由程序表达式 +Infinity(简作 Infinity) 和 -Infinity 产生,并假设执行程序不能调整定义的全局变量 Infinity,在javascript中global全局对象的一个Infinity属性window.Infinity)。
  • 另外 18437736874454810624(即,264-253)个值被称为有限数值,其中的一半是正数,另一半是负数,对于每个正数而言,都有一个与之对应的、相同规模的负数。
  • 请注意,还有一个正零和一个负零。
  • 查看number类型数值的二进制

数轴:

[200] [400]

对于这个如果有兴趣细扣就点这里还有这里

整数

整数可以被表示成十进制(基数为10)、十六进制(基数为16)以及八进制(基数为8)。

  • 十进制:十进制整数字组成的数字序列,不带前导0(零)。
  • 八进制:八进制整数只能包括数字0-7,通过在八进制整数前面加前导0(零)或者或0o的数值来表示八进制整数。八进制整数只包含 0 到 7 的数字。具有前导0并包含数字“8”和/或“9”的数字将被解释为十进制数字,具有前导0o并包含数字“8”和/或“9”的数字将会报错。
  • 十六进制:通过在整数前面加前导“0x”(零和 x|X)来表示十六进制(“hex”)整数。字母 A 到 F 以单个数字的形式表示以 10 为基数的 10 到 15。字母 A 到 F 用于以单个数字的形式表示以 10 为基数的 10 到 15。即,0xF 相当于 15,0x10 相当于 16。
  • 二进制:有前缀0b0B的数值。

在进行算术计算时,所有以八进制和十六进制表示的数值最终都将被转换成十进制数值,还有严格模式下禁止使用八进制。

1
2
3
4
5
6
7
8
9
10
11
12
//默认情况下,JavaScript内部会自动将八进制、十六进制、二进制转为十进制。    
0xff // 255
-0xF1A7// -61863
0o377 // 255
015 // 13
019 // 19
0b11 // 3

//如果八进制、十六进制、二进制的数值里面,出现不属于该进制的数字,就会报错。
0xzz // 报错
0o88 // 报错
0b22 // 报错

IEBUG:从 Internet Explorer 9 标准模式、Internet Explorer 10 标准模式、Internet Explorer 11 标准模式和 Windows 应用商店应用 开始,parseInt 函数不将前缀为“0”的字符串视为八进制。但在不使用 parseInt 函数时,前缀为“0”的字符串仍可被解释为八进制。

浮点值

  • 一个十进制整数,它可以带符号(即前面的“+”或“ - ”号),
  • 一个小数点(“.”),
  • 一个小数部分(由一串十进制数表示),
  • 一个指数部分
    指数部分是以“e”或“E”开头后面跟着一个整数,可以有正负号(即前面写“+”或“-”)。一个浮点数字面值必须至少有一位数字,后接小数点或者“e”(大写“E”也可)组成。一些浮点数字面值的例子,如3.1415,-3.1E13,.1e12以及2E-12。
    简言之,其语法是:

    [digits][.digits][(E|e)[(+|-)]digits]
    //实例:
    3.14
    2345.789
    .3333333333333333333 // 0 可以省略

以下两种情况,JavaScript会自动将数值转为科学计数法表示,其他情况都采用字面形式直接表示。

  • 小数点前的数字多于21位

    1
    console.log(1234567890123456789012)    // 1.2345678901234568e+21
  • 小数点后的零多于5个

    1
    console.log(0.0000003) //3e-7

NaN

NaN(not a number)用于处理计算中出现的错误情况,比如 0.0 除以 0.0 或者求负数的平方根。由上面的表中可以看出,对于单精度浮点数,NaN 表示为指数为 emax + 1 = 128(指数域全为 1),且尾数域不等于零的浮点数。IEEE 标准没有要求具体的尾数域,所以 NaN 实际上不是一个,而是一族,它是全局对象global对象的一个属性(window.NaN)。
需要注意的是,NaN不是一种独立的数据类型,而是一种特殊数值,它的数据类型依然属于Number,使用typeof运算符可以看得很清楚。

1
console.log(typeof NaN) // 'number

特性:

  • NaN不等于任何值,包括它本身。NaN === NaN // false
  • 由于数组的indexOf方法,内部使用的是严格相等运算符,所以该方法对NaN不成立。NaN].indexOf(NaN) // -1
  • NaN在布尔运算时被当作false。Boolean(NaN) // false
  • NaN与任何数(包括它自己)的运算,得到的都是NaN。
1
2
3
4
NaN + 32 // NaN
NaN - 32 // NaN
NaN * 32 // NaN
NaN / 32 // NaN

判断NaN的方法 isNaN

1
2
isNaN(NaN) // true
isNaN(123) // false

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

1
2
3
4
5
6
7
8
9
10
11
isNaN('Hello') // true
// 等同于
isNaN(Number('Hello')) // true

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

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

但是,对于空数组和只有一个数值成员的数组,isNaN返回false

1
2
3
isNaN([]) // false
isNaN([123]) // false
isNaN(['123']) // false

上面的代码之所以返回false,原因是这些数组能被Number函数转成数值,请参见《数据类型转换》一节。

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

1
2
3
4
5
6
7
8
function myIsNaN(value) {
return typeof value === 'number' && isNaN(value);
}
判断NaN更可靠的方法是,利用`NaN`是JavaScript之中唯一不等于自身的值这个特点,进行判断。

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

+0 和 -0

先看一道题: 假如 A === B 并且 1/A < 1/B; 请问 A 等于 几?

产生原因

数字需要被编码才能进行数字化存储.举个例子,假如我们要将一个整数编码为4位的二进制数,使用原码(sign-and-magnitude)方法,则最高位是符号位(0代表正,1代表负),剩下的三位表示大小(具体的值).因此,−2和+2会编码成为下面这样:

1010 // +2
0010 // -2
这就意味着将会有两个零:
1000 // -0
0000 // +0

在JavaScript中,所有的数字都是浮点数,都是根据IEEE-754标准中的浮点数算法以双精度格式被编码。这个标准中正负号的处理方式类似于原码(sign-and-magnitude)方法中整数的编码方式,所以也有正负零。

参与运算

1
2
3
4
5
6
7
8
9
10
11
+0 === -0 //true 虽然有正0和负0但是他们两个是相等
-0 < +0 //false
+0 < -0 //false

-0 + -0 // -0
-0 + +0 // +0
+0 X -5 // -0
-0 X -5 // +0
1 / +0 // Infinity
1 / -0 // -Infinity
+0 / -0 // NaN

参与Math对象的方法

  • Math.pow(x,y)方法可返回从 之间的角度。
1
2
Math.pow(+0, -1) // Infinity
Math.pow(-0, -1) // -Infinity
  • Math.atan2(x,y)方法可返回从 xy 的值。
1
2
3
4
5
6
7
8
9
10
11
x = 0 , y <= -0     // π(3.141592653589793)
Math.atan2(+0, -0) // π(3.141592653589793)

x = 0 , y >= 0 // 0
Math.atan2(+0, +0) // 0

x = -0 , y >= +0 // -0
Math.atan2(-0, +0) // -0

x = -0 , y <= -0 // -π(-3.141592653589793)
Math.atan2(-0, -0) // -π(-3.141592653589793)
  • Math.round()是另外一个参数不为零却产生-0结果的操作:
    1
    Math.round(-0.1) // -0

区分这两个零

方法1: 判断一个零是正还是负的标准解法是用它除1,然后看计算的结果是-Infinity还是+Infinity

1
2
3
function isNegativeZero(x) {
return x === 0 && (1/x < 0);
}

方法2: 除了上面讲的几种解法.还有一个解法来自Allen Wirfs-Brock(译者注:TC39编辑,ES标准就是他写出来的。):

1
2
3
4
5
6
7
8
9
10
11
12
function isNegativeZero(x) {
if (x !== 0) return false;
var obj = {};
Object.defineProperty(obj, 'z', { value: -0, configurable: false });
try {
// 如果x的值和z属性的当前值不相等的话,就会抛出异常.
Object.defineProperty(obj, 'z', { value: x });
} catch (e) {
return false
};
return true;
}

解释: 通常情况下,你不能重新定义一个不可配置的对象属性,否则会抛出异常:TypeError: Cannot redefine property: z可是,如果你重新定义属性时指定的属性特性的值与该特性当前的值相等,则JavaScript会忽略掉这个重定义,不会抛出异常。其中在判断两个值是否相等时使用的运算不是===,是一个称之为SameValue的内部算法,该算法可以区分开 -0 和 +0 。可以从Wirfs-Brock的原文中了解更多细。(冻结一个对象会让该对象的所有属性变的不可配置)。

SameValue 算法
内部严格比较操作 SameValue(x,y),x 和 y 为 ECMAScript 语言中的值,需要产出 true 或 false。Note.png Note.png V8.png

比较过程如下:

如果 Type(x) 与 Type(y) 的结果不一致,返回 false,否则
如果 Type(x) 结果为 Undefined,返回 true
如果 Type(x) 结果为 Null,返回 true
如果 Type(x) 结果为 Number,则
如果 x 为 NaN,且 y 也为 NaN,返回 true
如果 x 为 +0,y 为 -0,返回 false
如果 x 为 -0,y 为 +0,返回 false
如果 x 与 y 为同一个数字,返回 true
返回 false
如果 Type(x) 结果为 String,如果 x 与 y 为完全相同的字符序列(相同的长度和相同的字符对应相同的位置),返回 true,否则,返回 false
如果 Type(x) 结果为 Boolean,如果 x 与 y 都为 true 或 false,则返回 true,否则,返回 false
如果 x 和 y 引用到同一个 Object 对象,返回 true,否则,返回 false

在执行一些特殊方法的时候,比如alert或innerHTML等方法,它将由脚本解析器自动调用toString()方法。

看完上面这些,那么这节开头的题目的结果自然而然就知道喽。

Infinity

Infinity 表示“无穷”,挂在global对象下的Infinity属性上(window.Infinity)。除了0除以0得到NaN,其他任意数除以0,得到Infinity。获得方式

1
2
3
4
Number.NEGATIVE_INFINITY // +infinity
Number.POSITIVE_INFINITY // -infinity

window.Infinity === Number.POSITIVE_INFINITY // ture
1
2
1 / -0 // -Infinity
1 / +0 // Infinity

正负之分

和+0-0 不同,Infinity 不等于 -Infinity

1
Infinity === -Infinity // false

产生原因

1
2
3
4
5
6
Math.pow(+0, -1) // Infinity
Math.pow(-0, -1) // -Infinity

//运算结果超出JavaScript可接受范围,也会返回无穷。
Math.pow(2, 2048) // Infinity
-Math.pow(2, 2048) // -Infinity

参与运算

Infinity的四则运算,符合无穷的数学计算规则。

1
2
3
4
5 * Infinity // Infinity
5 - Infinity // -Infinity
Infinity / 5 // Infinity
5 / Infinity // 0
1
2
3
4
5
Infinity - Infinity // NaN
Infinity / Infinity // NaN

Infinity + Infinity // Infinity
Infinity * Infinity // Infinity

nfinity可以用于布尔运算。可以记住,Infinity是JavaScript中最大的值(NaN除外),-Infinity是最小的值(NaN除外)。

1
2
5 > -Infinity // true
5 > Infinity // false

由于数值正向溢出(overflow)、负向溢出(underflow)和被0除,JavaScript都不报错,所以单纯的数学运算几乎没有可能抛出错误。

isFinite函数

isFinite函数返回一个布尔值,检查某个值是否为正常值,而不是Infinity。

1
2
3
4
isFinite(Infinity) // false
isFinite(-1) // true
isFinite(true) // true
isFinite(NaN) // false //如果对NaN使用isFinite函数,也返回false,表示NaN不是一个正常值

数值转换

Number()

使用Number函数,可以将任意类型的值(parseInt和parseFloat只能转换字符串和数值类型)转化成数字。

  • 简单类型转换规则

    • 数值:转换为十进制(因为默认调用toString(),会以十进制输出)。

      1
      2
      3
      4
      5
      6
      7
      Number(10);     // 10 
      Number(010); // 8
      Number(090); // 90 因为八进制中没有9,所以按照十进制处理
      Number(0x16); // 22

      Number(0o10); // 在chrome和firefox为8,IE报错 `缺少 “)”`
      Number(0b1000); // 在chrome和firefox为8,IE报错 `缺少 “)”`
    • 字符串:先去掉字符串前后的空格,如果可以被解析为数值,则转换为相应的数值,否则得到NaN。空字符串""转为0

      • 如果字符串是Number("0o17")Number("0b10000")(包括前面带正号或负号的情况)在chrome和firefox会按照八进制转换为十进制 16,但是IE不会生产NaN,十六进制没问题chrome和firefox、IE没问题。
      • 如果字符串中包含有效的浮点格式,如”1.1”,则将其转换为对应的浮点数值(同样,也会忽略前导零)。
    • 布尔值:true转成 1,false 转成 0。

    • undefined:转成NaN

    • null:转成0。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      Number("324") // 324
      Number(" -9.8 ") // -9.8

      Number("010") // 10 和parseInt("010")为不同
      Number("0o17")// 在chrome和firefox为16。IE为NaN。
      Number("0b10000") // 在chrome和firefox为16。IE为NaN。
      Number("0x10") // 在chrome和firefox为16。IE也为16。

      Number("324abc") // NaN

      Number("") // 0

      Number(false) // 0

      Number(undefined) // NaN

      Number(null) // 0
  • 对象的转换规则
    对象的转换规则比较复杂。

    1. 先调用对象自身的valueOf方法,如果该方法返回原始类型的值(数值、字符串和布尔值),则直接对该值使用Number方法,不再进行后续步骤。
    2. 如果valueOf方法返回复合类型的值,再调用对象自身的toString方法,如果toString方法返回原始类型的值,则对该值使用Number方法,不再进行后续步骤。
    3. 如果toString方法返回的是复合类型的值,则报错。

      1
      2
      3
      Number({a:1,valueOf:function(){return "5"}}); //5  先调用对象自身的`valueOf`方法,如果该方法返回原始类型的值(数值、字符串和布尔值),则直接对该值使用`Number`方法,不再进行后续步骤。
      Number({a:1,valueOf:function(){return {b:5}},toString:function(){return 4}}); //4 如果`valueOf`方法返回复合类型的值,再调用对象自身的`toString`方法,如果`toString`方法返回原始类型的值,则对该值使用`Number`方法,不再进行后续步骤。
      Number({a:1,valueOf:function(){return {b:5}},toString:function(){return {}}}); //TypeError: Cannot convert object to primitive value 如果`toString`方法返回的是复合类型的值,则报错。

parseInt()

  • 基本用法
    parseInt()方法可以将字符串转化为整数。如果字符串头部有空格,空格会被自动去除。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    parseInt('8a') // 8
    parseInt(" -12 ba") //-12

    //十六进制
    parseInt('0xf00') // 3840 开头两个字符是`0x`或`0X`,`parseInt`将其视为十六进制数
    //八进制
    parseInt('056') // 56
    parseInt('0o56') // 0
    parseInt('0O56') // 0
    //二进制
    parseInt("0B10") // 0

    上面代码中,parseInt的参数都是字符串,结果只返回字符串头部可以转为数字的部分。最后一行的0xf00之所以可以转为数字,因为如果开头两个字符是0x0XparseInt将其视为十六进制数,但是八进制和二进制确默认视为普通字符串。
    如果字符串的第一个非空格字符不能转化为数字(数字的正负号除外),返回NaN

    1
    2
    3
    4
    5
    parseInt('abc') // NaN
    parseInt('.3') // NaN
    parseInt('') // NaN 不同于Number()
    parseInt(null) // NaN 不同于Number()
    parseInt('+') // NaN
  • 进制转换
    parseInt()方法还可以接受第二个参数(2到36之间,超出区间(包括负数但0除外)返回NaN),表示被解析的值的进制,返回该值对应的十进制数。
    如果第二个参数不是数值,会被自动转为(调用Number())一个整数,这个整数只有在2到36之间,才能得到有意义的结果,超出这个范围,则返回NaN,如果转换的结果为0,NaN,都会直接忽略返回原值。
    如果第二个参数是0undefinednull等等一些不能转为正常整数的值,则直接忽略。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    parseInt(1000, 2) // 8
    parseInt(1000, 6) // 216
    parseInt(1000, 8) // 512
    //特殊情况
    parseInt(1000, "8") // 512 把"8"自动转为8
    parseInt(1000, " +8 ") // 512 会自动去掉前置和后置空格
    parseInt(1000, " -8 ") // NaN 负数超出范围
    parseInt(1000, 1) // NaN 超出范围
    parseInt(1000, 37) // NaN 超出范围
    parseInt(1000, "8aa") // 1000 因为Number("8aa")等于NaN
    parseInt(1000, 0) // 1000 直接忽略返回原值
    parseInt(1000, NaN) // 1000
    parseInt(1000, null) // 1000 因为Number(NaN)等于0
    parseInt(1000, undefined) // 1000 因为Number(undefined)等于NaN
    parseInt("1000", {
    a:1,
    valueOf:function(){
    return 5;
    }
    }) //125 因为Number({a:1,valueOf:function(){return 5;}}) 返回5 所以
  • 特别注意
    需要注意的是,进制转换的时候,参数是字符串或数值,parseInt的行为不一致。
  1. 如果第一个参数是数值,会将这个数值先转为十进制,然后再应用第二个参数。

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

    上面代码中,0x11会被先转为十进制的17,然后再用36进制解读这个17,最后返回结果43。

  2. 如果第一个参数是字符串,则会直接用指定进制解读这个字符串。

    1
    2
    parseInt('0x11', 36) // 42805
    parseInt('x', 36) // 33

    上面代码中,字符串0x11会被直接当作一个36进制的数。由于字符x在36进制中代表33,导致0x11被解读为42805。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    parseInt(010, 10) // 8
    parseInt('010', 10) // 10

    parseInt(010, 2) // NaN 因为`010数值`转换为十进制是8,而8在二进制是不存在的所以返回`NaN`
    parseInt('010', 2) // 2

    parseInt(010, 8) // NaN 因为`010数值`转换为十进制是8,而8在八进制是不存在的所以返回`NaN`
    parseInt('010', 8) // 8

    parseInt(020, 10) // 16
    parseInt('020', 10) // 20

    parseInt(020, 8) // 14 因为`020数值`转换为十进制是16,再转换为8进制刚好14
    parseInt('020', 8) // 16 因为`020字符串`转换为十进制是20,再转换为8进制刚好16

    上面代码中,010会被先转为十进制8,然后再应用第二个参数,由于二进制和八进制中没有8这个数字,所以parseInt(010, 2)parseInt(010, 8)返回NaN。同理,数值020会被先转为十进制的16,然后再应用第二个参数。

    parseInt的很多复杂行为,都是由八进制的前缀0引发的,这增加编程处理的复杂性。因此,ECMAScript 5不再允许parseInt将带有前缀0的数字,视为八进制数,而是要求忽略这个0。但是,为了保证兼容性,大部分浏览器并没有部署这一条规定。

  3. 如果第一个参数是以0x0X开头的字符串,而第二个参数省略或为0,则parseInt自动将第二个参数设为16。

    1
    2
    3
    4
    5
    6
    parseInt('0xFF') // 255
    parseInt('0xFF', 0) // 255
    parseInt('0xFF', 16) // 255

    parseInt('0xFF', 10) // 0
    parseInt('0xFF', 17) // 0

    上面代码中,第二个参数除了0、16和省略,其他情况都会依次解析第一个参数,直到遇到第一个不可解析字符。

  4. 如果参数是对象,数据或者{}
    和Number()过程相反,先调用 toString(),如果返回的不是 简单数据类型则再调用valueOf方法。
    parseInt({a:1,valueOf:function(){return 5},toString:function(){return 4}});// 4
    parseInt([2,3]);//2因为数组的valueOf返回还是数组,继续调用toString方法,返回"2,3",再parseInt返回 2

  5. 科学计数法产生的扯淡问题
    对于那些会自动转为科学计数法的数字,parseInt会将科学计数法的表示方法视为字符串,因此导致一些奇怪的结果。

    1
    2
    3
    4
    5
    6
    7
    parseInt(1000000000000000000000.5, 10) // 1
    // 等同于
    parseInt('1e+21', 10) // 1

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

parseFloat()

  • 基本用法
    parseFloat`方法用于将一个字符串转为浮点数。
    1
    parseFloat("3.14") // 3.14
  1. 如果字符串符合科学计数法,则会进行相应的转换。

    1
    2
    parseFloat('314e-2') // 3.14
    parseFloat('0.0314E+2') // 3.14
  2. 如果字符串包含不能转为浮点数的字符,则不再进行往后转换,返回已经转好的部分。

    1
    parseFloat('3.14more non-digit characters') // 3.14

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

    1
    parseFloat('\t\v\r12.34\n ') // 12.34
  3. 如果参数不是字符串,或者字符串的第一个字符不能转化为浮点数,则返回NaN

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    parseFloat([]) // NaN
    parseFloat('FF2') // NaN

    parseFloat(true) // NaN 不同于`Number`函数
    Number(true) // 1

    parseFloat(null) // NaN 不同于`Number`函数
    Number(null) // 0

    parseFloat('') // NaN 不同于`Number`函数
    Number('') // 0

    parseFloat('123.45#') // 123.45 不同于`Number`函数
    Number('123.45#') // NaN
    1. 如果参数是对象,数据或者{}
      和Number()过程相反,先调用 toString(),如果返回的不是 简单数据类型则再调用valueOf方法。
      parseFloat({a:1,valueOf:function(){return 5},toString:function(){return 4}});// 4
      parseInt([2,3]);//2因为数组的valueOf返回还是数组,继续调用toString方法,返回"2,3",再parseInt返回 2

特别注意:parseInt()parseFloat()会先调用值的toString()方法,Number()是先调用valueOf,返回结果有问题再调用toString

1
2
3
4
5
6
7
8
9
10
11
12
13
parseInt({
a: 1,
toString: function(){
return "11"
}
});

parseFloat({
a: 1,
toString: function(){
return "11"
}
});

上面这两种情况也会正确的返回11,看到这儿你会说“你不是说parseInt只能转换字符串”吗?其实真正的原因是,所有的转换第一步都是调用toString()方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Number.prototype.toString = function(){
console.log("我被调用了")
return 123123;
}
Number.prototype.valueOf = function(){
console.log("我被调用了-valueOf")
return 123123;
}

var a = new Number(12);


parseInt(a) // 我被调用了 123123
Number(a) // 我被调用了-valueOf 123123

上面这段code 足以证明特别注意
详见:Ex igne vita

引用:

紫云飞
阮一峰

文章目录
  1. 1. Number类型
    1. 1.1. 整数
    2. 1.2. 浮点值
    3. 1.3. NaN
      1. 1.3.1. 特性:
      2. 1.3.2. 判断NaN的方法 isNaN
    4. 1.4. +0 和 -0
      1. 1.4.1. 产生原因
      2. 1.4.2. 参与运算
      3. 1.4.3. 参与Math对象的方法
      4. 1.4.4. 区分这两个零
    5. 1.5. Infinity
      1. 1.5.1. 正负之分
      2. 1.5.2. 产生原因
      3. 1.5.3. 参与运算
      4. 1.5.4. isFinite函数
  2. 2. 数值转换
    1. 2.1. Number()
    2. 2.2. parseInt()
    3. 2.3. parseFloat()