## 一、概述
### 1.1 整數和浮點數
JavaScript 內部,所有數字都是以64位浮點數形式儲存,即使整數也是如此。所以,`1`與`1.0`是相同的,是同一個數。
~~~
1 === 1.0 // true
~~~
這就是說,JavaScript 語言的底層根本沒有整數,所有數字都是小數(64位浮點數)。
### 1.2 數值精度
根據國際標準 IEEE 754,JavaScript 浮點數的64個二進制位,從最左邊開始,是這樣組成的。
* 第1位:符號位,`0`表示正數,`1`表示負數
* 第2位到第12位(共11位):指數部分
* 第13位到第64位(共52位):小數部分(即有效數字)
符號位決定了一個數的正負,指數部分決定了數值的大小,小數部分決定了數值的精度。
指數部分一共有11個二進制位,因此大小范圍就是0到2047。IEEE 754 規定,如果指數部分的值在0到2047之間(不含兩個端點),那么有效數字的第一位默認總是1,不保存在64位浮點數之中。因此,JavaScript 提供的有效數字最長為53個二進制位。
~~~
(-1)^符號位 * 1.xx...xx * 2^指數部分
~~~
精度最多只能到53個二進制位,這意味著,絕對值小于2的53次方的整數,即-2^53到2^53,都可以精確表示。大于2的53次方以后,多出來的有效數字(最后三位的`111`)都會無法保存,變成0。
~~~
Math.pow(2, 53)
// 9007199254740992
// 多出的三個有效數字,將無法保存
9007199254740992111
// 9007199254740992000
~~~
### 1.3 數值范圍
根據標準,64位浮點數的指數部分的長度是11個二進制位,意味著指數部分的最大值是2047(2的11次方減1)。也就是說,64位浮點數的指數部分的值最大為2047,分出一半表示負數,則 JavaScript 能夠表示的數值范圍為2^-1023到2^1024(開區間),超出這個范圍的數無法表示。
如果一個數大于等于2的1024次方,那么就會發生“正向溢出”,即 JavaScript 無法表示這么大的數,這時就會返回`Infinity`。
~~~
Math.pow(2, 1024) // Infinity
~~~
如果一個數小于等于2的-1075次方(指數部分最小值-1023,再加上小數部分的52位),那么就會發生為“負向溢出”,即 JavaScript 無法表示這么小的數,這時會直接返回0。
~~~
Math.pow(2, -1075) // 0
~~~
## 二、數值的表示法
JavaScript 的數值有多種表示方法,可以用字面形式直接表示,比如`35`(十進制)和`0xFF`(十六進制)。
數值也可以采用科學計數法表示,科學計數法允許字母`e`或`E`的后面,跟著一個整數,表示這個數值的指數部分。
~~~
123e3 // 123000
123e-3 // 0.123
-3.1E+12
.1e-23
~~~
以下兩種情況,JavaScript 會自動將數值轉為科學計數法表示,其他情況都采用字面形式直接表示。
* 小數點前的數字多于21位。
~~~
1234567890123456789012
// 1.2345678901234568e+21
123456789012345678901
// 123456789012345680000
~~~
* 小數點后的零多于5個。
~~~
// 小數點后緊跟5個以上的零,
// 就自動轉為科學計數法
0.0000003 // 3e-7
// 否則,就保持原來的字面形式
0.000003 // 0.000003
~~~
## 三、數值的進制
使用字面量(literal)直接表示一個數值時,JavaScript 對整數提供四種進制的表示方法:十進制、十六進制、八進制、二進制。
* 十進制:沒有前導0的數值。
* 八進制:有前綴`0o`或`0O`的數值,或者有前導0、且只用到0-7的八個阿拉伯數字的數值。
* 十六進制:有前綴`0x`或`0X`的數值。
* 二進制:有前綴`0b`或`0B`的數值。
默認情況下,JavaScript 內部會自動將八進制、十六進制、二進制轉為十進制。
~~~
0xff // 255
0o377 // 255
0b11 // 3
~~~
## 四、特殊數值
### 4.1 正零和負零
前面說過,JavaScript 的64位浮點數之中,有一個二進制位是符號位。這意味著,任何一個數都有一個對應的負值,就連`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`當作分母,返回的值是不相等的。
```
(1 / +0) === (1 / -0) // false
```
### 4.2 NaN
`NaN`是 JavaScript 的特殊值,表示“非數字”(Not a Number),主要出現在將字符串解析成數字出錯的場合。
~~~
5 - 'x' // NaN
~~~
上面代碼運行時,會自動將字符串`x`轉為數值,但是由于`x`不是數值,所以最后得到結果為`NaN`,表示它是“非數字”。
另外,一些數學函數的運算結果會出現`NaN`。
~~~
Math.log(-1) // NaN
Math.sqrt(-1) // NaN
~~~
`0`除以`0`也會得到`NaN`。
~~~
0 / 0 // NaN
~~~
* `NaN`不等于任何值,包括它本身。
~~~
NaN === NaN // false
~~~
* `NaN`與任何數(包括它自己)的運算,得到的都是`NaN`。
```
NaN + 32 // NaN
NaN - 32 // NaN
NaN * 32 // NaN
NaN / 32 // NaN
```
### 4.3 Infinity
`Infinity`表示“無窮”,用來表示兩種場景。一種是一個正的數值太大,或一個負的數值太小,無法表示;另一種是非0數值除以0,得到`Infinity`。
```
// 場景一:一個表達式的計算結果太大,超出了能夠表示的范圍
Math.pow(2, 1024)
// Infinity
// 場景二:非0數值除以0
0 / 0 // NaN
1 / 0 // Infinity
```
`Infinity`有正負之分,`Infinity`表示正的無窮,`-Infinity`表示負的無窮。`Infinity`大于一切數值(除了`NaN`),`-Infinity`小于一切數值(除了`NaN`)。
~~~
Infinity === -Infinity // false
1 / -0 // -Infinity
-1 / -0 // Infinity
Infinity > 1000 // true
-Infinity < -1000 // true
Infinity > NaN // false
-Infinity > NaN // false
Infinity < NaN // false
-Infinity < NaN // false
~~~
* 0乘以`Infinity`,返回`NaN`;0除以`Infinity`,返回`0`;`Infinity`除以0,返回`Infinity`。
~~~
0 * Infinity // NaN
0 / Infinity // 0
Infinity / 0 // Infinity
~~~
* `Infinity`加上或乘以`Infinity`,返回的還是`Infinity`。
~~~
Infinity + Infinity // Infinity
Infinity * Infinity // Infinity
~~~
* `Infinity`減去或除以`Infinity`,得到`NaN`。
~~~
Infinity - Infinity // NaN
Infinity / Infinity // NaN
~~~
* `Infinity`與`null`計算時,`null`會轉成0,等同于與`0`的計算。
```
null * Infinity // NaN
null / Infinity // 0
Infinity / null // Infinity
```
* `Infinity`與`undefined`計算,返回的都是`NaN`。
~~~
undefined + Infinity // NaN
undefined - Infinity // NaN
undefined * Infinity // NaN
undefined / Infinity // NaN
Infinity / undefined // NaN
~~~
## 五、與數值相關的全局方法
### 5.1 parseInt()
`parseInt`方法用于將字符串轉為整數。
~~~
parseInt('123') // 123
~~~
* 如果字符串頭部有空格,空格會被自動去除。
~~~
parseInt(' 81') // 81
~~~
* 字符串轉為整數的時候,是一個個字符依次轉換,如果遇到不能轉為數字的字符,就不再進行下去,返回已經轉好的部分。
```
parseInt('8a') // 8
parseInt('12**') // 12
parseInt('12.34') // 12
parseInt('15e2') // 15
parseInt('15px') // 15
```
* 如果字符串的第一個字符不能轉化為數字(后面跟著數字的正負號除外),返回`NaN`。
~~~
parseInt('abc') // NaN
parseInt('.3') // NaN
parseInt('') // NaN
parseInt('+') // NaN
parseInt('+1') // 1
~~~
所以,`parseInt`的返回值只有兩種可能,要么是一個十進制整數,要么是`NaN`。
### 5.2 parseFloat()
`parseFloat`方法用于將一個字符串轉為浮點數。
~~~
parseFloat('3.14') // 3.14
~~~
* 如果字符串包含不能轉為浮點數的字符,則不再進行往后轉換,返回已經轉好的部分。
~~~
parseFloat('3.14more non-digit characters') // 3.14
~~~
* `parseFloat`方法會自動過濾字符串前導的空格。
~~~
parseFloat(' 12.34') // 12.34
~~~
* 如果參數不是字符串,或者字符串的第一個字符不能轉化為浮點數,則返回`NaN`。
~~~
parseFloat([]) // NaN
parseFloat('FF2') // NaN
parseFloat('') // NaN
~~~
上面代碼中,尤其值得注意,`parseFloat`會將空字符串轉為`NaN`。
### 5.3 isNaN()
`isNaN`方法可以用來判斷一個值是否為`NaN`。
~~~
isNaN(NaN) // true
isNaN(123) // false
~~~
但是,`isNaN`只對數值有效,如果傳入其他值,會被先轉成數值。比如,傳入字符串的時候,字符串會被先轉成`NaN`,所以最后返回`true`,這一點要特別引起注意。也就是說,`isNaN`為`true`的值,有可能不是`NaN`,而是一個字符串。
~~~
isNaN('Hello') // true
// 相當于
isNaN(Number('Hello')) // true
~~~
因此,使用`isNaN`之前,最好判斷一下數據類型。
~~~
// 判斷 value 是否為 NaN 的方法
function myIsNaN(value) {
return typeof value === 'number' && isNaN(value);
}
// 或者利用 NaN 為唯一不等于自身的值的這個特點
function myIsNaN(value) {
return value !== value;
}
~~~
### 5.4 isFinite()
`isFinite`方法返回一個布爾值,表示某個值是否為正常的數值。
~~~
isFinite(Infinity) // false
isFinite(-Infinity) // false
isFinite(NaN) // false
isFinite(undefined) // false
isFinite(null) // true
isFinite(-1) // true
~~~
除了`Infinity`、`-Infinity`、`NaN`和`undefined`這幾個值會返回`false`,`isFinite`對于其他的數值都會返回`true`。
- 階段一 Java 零基礎入門
- 步驟1:基礎語法
- 第01課 初識
- 第02課 常量與變量
- 第03課 運算符
- 第04課 選擇結構
- 第05課 循環結構
- 第06課 一維數組
- 第08課 方法
- 第09課 數組移位與統計
- 第10課 基礎語法測試
- 第09課 基礎語法測試(含答案)
- 步驟2:面向對象
- 第01課 類和對象
- 第02課 封裝
- 第03課 學生信息管理
- 第04課 繼承
- 第05課 單例模式
- 第06課 多態
- 第07課 抽象類
- 第08課 接口
- 第09課 內部類
- 第10課 面向對象測試
- 第10課 面向對象測試(含答案)
- 步驟3:常用工具類
- 第01課 異常
- 第02課 包裝類
- 第03課 字符串
- 第04課 集合
- 第05課 集合排序
- 第06課 泛型
- 第07課 多線程
- 第08課 輸入輸出流
- 第09課 案例:播放器
- 第10課 常用工具測試(一)
- 第10課 常用工具測試(一)(答案)
- 第10課 常用工具測試(二)
- 第10課 常用工具測試(二)(答案)
- 階段二 從網頁搭建入門 JavaWeb
- 步驟1:HTML 與 CSS
- 第01課 HTML 入門
- 第01課 HTML 入門(作業)
- 第02課 CSS 入門
- 第02課 CSS 入門(作業)
- 第03課 CSS 布局
- 第03課 CSS 布局(作業)
- 步驟2:JavaScript 與前端案例
- 第01課 JavaScript 入門
- 第01課 JavaScript 入門(作業)
- 第02課 仿計算器
- 第03課 前端油畫商城案例
- 第04課 輪播圖
- 第05課 網頁搭建測試
- 第05課 網頁搭建測試(含答案)
- 步驟3:JavaScript 教程
- 入門
- 概述
- 基本語法
- 數據類型
- 概述
- 數值
- 字符串
- undefined, null 和布爾值
- 對象
- 函數
- 數組
- 運算符
- 算術運算符
- 比較運算符
- 布爾運算符
- 位運算符
- 運算順序
- 語法專題
- 數據類型的轉換
- 錯誤處理機制
- 標準庫
- String
- Date
- Math
- DOM
- 概述
- Document 節點
- 事件
- EventTarget 接口
- 事件模型
- 常見事件
- 階段三 數據庫開發與實戰
- 步驟1:初始數據庫操作
- 第01課 數據類型
- 第02課 表的管理
- 第03課 數據管理
- 第04課 常用函數
- 第05課 JDBC 入門
- 第06課 Java 反射
- 第07課 油畫商城
- 第08課 數據庫基礎測試
- 步驟2:MyBatis 從入門到進階
- 第01課 IntelliJ IDEA 開發工具入門
- 第02課 Maven 入門
- 第03課 工廠模式
- 第04課 MyBatis 入門
- 第05課 MyBatis 進階
- 第06課 商品信息管理
- 第07課 MyBatis 基礎測試
- 步驟3:Redis 數據庫與 Linux 下項目部署
- 第01課 Linux 基礎
- 第02課 Linux 下 JDK 環境搭建及項目部署
- 第03課 Redis 入門
- 階段四 SSM 到 Spring Boot 入門與綜合實戰
- 步驟1:Spring 從入門到進階
- 第01課 Spring 入門
- 第02課 Spring Bean 管理
- 第03課 Spring AOP
- 第04課 基于 AspectJ 的 AOP 開發
- 第05課 JDBC Template
- 第06課 Spring 事務管理
- 第07課 人員管理系統開發
- 第08課 Spring 從入門到進階測試
- 步驟2:Spring MVC 入門與 SSM 整合開發
- 第01課 Spring MVC 入門與數據綁定
- 第02課 Restful 風格的應用
- 第03課 SpringMVC 攔截器
- 第04課 辦公系統核心模塊
- 步驟3:Spring Boot 實戰
- 第01課 Spring Boot 入門
- 第02課 校園商鋪項目準備
- 第03課 校園商鋪店鋪管理
- 第04課 校園商鋪商品管理及前臺展示
- 第05課 校園商鋪框架大換血
- 步驟4:Java 面試
- 第01課 面試準備
- 第02課 基礎面試技巧
- 第03課 Web基礎與數據處理
- 第04課 主流框架