《JavaScript語言入門教程》記錄整理:入門和資料型別
阿新 • • 發佈:2020-07-30
[toc]
本系列基於阮一峰老師的[《JavaScrip語言入門教程》](https://wangdoc.com/javascript/index.html)或《JavaScript教程》記錄整理,教程採用[知識共享 署名-相同方式共享 3.0協議](https://creativecommons.org/licenses/by-sa/3.0/deed.zh)。這幾乎是學習js最好的教程之一(去掉之一都不過分)
最好的教程而阮一峰老師又採用開源方式共享出來,之所以重新記錄一遍,一是強迫自己重新認真讀一遍學一遍;二是對其中知識點有個自己的記錄,加深自己的理解;三是感謝這麼好的教程,希望更多人閱讀了解
# 入門篇
## js介紹
1. JavaScript 是一種輕量級的指令碼語言和嵌入式(embedded)語言,其只能通過宿主環境(host,瀏覽器或node環境)提供I/O操作
2. 語法角度,JS是一種"物件模型"語言。支援函數語言程式設計、"面向物件"程式設計、程序式程式設計等
3. js核心語法包括:基本的語法構造(比如操作符、控制結構、語句)和標準庫(就是一系列具有各種功能的物件比如`Array`、`Date`、`Math`等)。然後就是宿主提供的API(比如瀏覽器提供的BOM、DOM和Web網際網路相關的類;Node環境提供檔案操作API、網路通訊API等)
4. JavaScript 的所有值都是物件
5. js可以採用事件驅動(`event-driven`)和非阻塞式(`non-blocking`)設計,實現高併發、多工處理
## 歷史
1. 1995年,Brendan Eich 只用了10天,完成了js的第一版,其設計借鑑了C、java、Scheme、Awk、Self、Perl、Python等多種語言,同時也留下了各種設計缺陷(導致常常需要學習各種解決問題的模式)
2. JavaScript與Java是兩種不同的語言,兩者的關係僅僅是js的基本語法和物件體系最開始是想要模仿Java,而後又與當時Java的公司Sun有合作,也藉助Java的聲勢,從而後來改名叫JavaScript
3. ECMAScript 和 JavaScript 的關係是,前者是後者的規格,後者是前者的一種實現。ECMAScript 只用來標準化 JavaScript 的基本語法結構。但其他標準如 DOM 的標準就是由 W3C組織(`World Wide Web Consortium`)制定的
4. 2007年,ECMAScript 4.0版草案發布,但是過於激進,導致後面中止了 ECMAScript 4.0 ,將其中一小部分功能釋出為ECMAScript 3.1。之後又將其改名為 ECMAScript 5。
5. 2015年6月,ECMAScript 6 正式釋出,且更名為“ECMAScript 2015”。之後每年釋出一個ECMAScript版本
6. [周邊大事記](https://wangdoc.com/javascript/basic/history.html#%E5%91%A8%E8%BE%B9%E5%A4%A7%E4%BA%8B%E8%AE%B0)
## 基本語法
1. js執行單位是行(line),一行一行地執行,一般,一行就是一個語句
2. 語句(statement)執行某種操作、表示式(expression)用於得到返回值。**凡是 JavaScript 語言中預期為值的地方,都可以使用表示式**(這一點使js某些使用很靈活)
3. 語句以分號結尾,一個分號表示一個語句結束。多個語句可以寫在一行內。分號前無內容,表示空語句。表示式不需要分號結尾
4. 變數是對“值”的具名引用,即為"值"取名。變數的名字就是變數名。如下使用var宣告一個變數a,並賦值1
```js
var a=1;
```
5. 只宣告變數而不賦值,則該變數的值是`undefined`,表示"無定義"。同時變數賦值時不寫`var`也有效,但不建議。變數必須先宣告再使用,否則會報錯`not defined`
6. 一條var命令可以宣告多個變數。js是動態型別語言,變數型別可以隨時更改。
```js
var a = 1;
a = 'hello';
```
7. 使用`var`重新宣告一個已存在的變數,是無效的,重新宣告時賦值,相當於重新賦值
8. **變數提升**:js的執行方式是,**先解析程式碼,獲取所有被宣告的變數,然後再一行一行地執行,這樣就會導致所有變數的宣告語句,會被提升到程式碼的頭部,這叫做變數提升(`hoisting`)**
9. **識別符號**(`identifier`)指的是識別各種值的合法名稱。比如變數名、函式名。js識別符號大小寫敏感。識別符號的命名規則是:只能以字母、下劃線(`_`)和美元符號(`$`)開頭,從第二個字元開始還可以使用數字。
10. js識別符號中的字母指的是`Unicode`字母。因此中文識別符號也可以使用
11. js中的保留字不能用於識別符號,保留字是指js中用來表示特定含義的字元,如return、class、true、false、function等
12. 註釋:註釋用來對程式碼進行解釋,js引擎執行時會忽略註釋部分。`//`表示單行註釋。`/* */`表示多行註釋
13. js使用大括號表示"區塊"(block)。對於`var`命令,js的區塊不構成單獨的作用域(`scope`)
14. 條件語句:
- `if`和`if...else...`結構,根據條件的布林值判斷執行。
- `switch`結構判斷表示式的值是否與`case`相符並執行,如果都不符則執行最後的`default`,`case`中`break`不能少,否則當前case程式碼塊執行完會接著執行下一個case。`switch`語句部分和`case`語句部分,都可以使用表示式,這就是js中可以為值的地方,都可以使用表示式的體現,如下:
```js
switch (1 + 3) {
case 2 + 2:
f();
break;
default:
neverHappens();
}
```
switch語句的值和case語句的值,比較時採用的是嚴格相等運算子(`===`)
- `?:`三元運算子:如下,條件`true`,執行"表示式1",否則執行"表示式2",然後獲取對應返回值
```js
(條件) ? 表示式1 : 表示式2
```
15. 迴圈語句:重複執行某個操作
- `while` 迴圈:迴圈條件和程式碼塊,條件為真,就迴圈執行程式碼塊
- `for` 迴圈:可以指定迴圈的起點、終點和終止條件。分為初始化表示式(initialize)、條件表示式(test)、遞增表示式(increment)
```js
for (初始化表示式; 條件; 遞增表示式) {
語句
}
```
所有for迴圈,都可以改寫成while迴圈
for語句的無線迴圈表示:
```js
for ( ; ; ){
console.log('Hello World');
}
```
- `do...while` 迴圈:先執行一次迴圈體,再判斷條件
- `break`語句用於跳出程式碼塊或迴圈。`continue`語句用於立即終止本輪迴圈,並開始下一輪迴圈
16. js語句的前面可以新增標籤(label),相當於定位符,用於跳轉到程式的任意位置
```js
label:
語句
```
# 資料型別
## 概述
1. JavaScript的資料型別有六種(ES6新增了 Symbol 型別)
- 數值(number):整數和小數(比如1和3.14)
- 字串(strin):文字(比如"Hello World")。
- 布林值(boolean):表示真偽的兩個特殊值,即`true`(真)和`false`(假)
- `undefined`:表示“未定義”或不存在,即由於目前沒有定義,所以此處暫時沒有任何值
- `null`:表示空值,即此處的值為空。
- 物件(object):各種值組成的集合。
數值、字串、布林值稱為原始型別(`primitive type`),是最基本的資料型別。物件稱為合成型別(`complex type`)。`undefined`和`null`兩個特殊值。
物件分為:狹義的物件(object)、陣列(array)、函式(function)
2. 型別判斷
`typeof`運算子返回一個值的資料型別:
- 數值、字串、布林值分別返回`number`、`string`、`boolean`
- 函式返回`function`,`undefined`返回`undefined`(可以檢測未宣告的變數),物件返回`object`,`null`返回`object`
```js
// 檢測未宣告
if (typeof v === "undefined") {
// ...
}
typeof window // "object"
typeof {} // "object"
typeof [] // "object"
typeof null // "object"
```
- `instanceof`可以區分陣列和物件
```js
[] instanceof Array // false
[] instanceof Array // true
```
## null 和 undefined
1. 兩者含義"類似",if語句中自動轉為false,相等於運算子(==)兩者比較為true。null表示"空"物件,轉為數值是`0`;`undefined`表示"無定義"的原始值,轉為數值是`NaN`
```js
Number(null) // 0
Number(undefined) // NaN
```
2. 函式沒有返回值時,預設返回 undefined
3. 布林值表示`true`和`false`兩個真假狀態。
4. **如果 JavaScript 預期某個位置應該是布林值,則會將該位置上現有的值自動轉為布林值。**
**下面六個值會被轉為`false`,其他的值都是`true`:**
- undefined
- null
- false
- 0
- NaN
- ""或''(空字串)
空陣列([])和空物件({})對應的布林值,都是`true`
## 數值
1. js中所有數字都是以64位浮點數儲存,整數也是如此。因此`1===1.0`,是同一個數
```js
1 === 1.0 // true
```
**JavaScript 語言的底層根本沒有整數,所有數字都是小數(64位浮點數)**
2. 浮點數不是精確的值,因此小數的比較和運算要特別注意
```js
0.1 + 0.2 === 0.3 // false
0.3 / 0.1 // 2.9999999999999996
(0.3 - 0.2) === (0.2 - 0.1) // false
```
3. js浮點數的64個二進位制位,從最左邊開始,由如下組成:
- 第1位:符號位,0表示正數,1表示負數。數值正負
- 第2位到第12位(共11位):指數部分。數值的大小
- 第13位到第64位(共52位):小數部分(即有效數字)。數值的精度
4. 絕對值小於2的53次方的整數,即$-2^53$到$2^53$,都可以精確表示
```js
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
```
5. 最大值和最小值:`Number.MAX_VALUE`和`Number.MIN_VALUE`
```js
Number.MAX_VALUE // 1.7976931348623157e+308
Number.MIN_VALUE // 5e-324
```
6. 數值表示法:`50`(十進位制)、`0xFF`(十六進位制)、`123e3`或`123e-3`(科學計數法)
7. 當小數點前面的數字多於21位時,或者小數點後的零多於5個時,js會自動將數值轉為科學計數法表示
8. 使用字面量(`literal`)表示數值時:
- 十進位制:沒有前導0的數值
- 八進位制:有字首`0o`或`0O`的數值,或者有前導`0`、且只用到0-7的八個阿拉伯數字的數值。
- 十六進位制:有字首`0x`或`0X`的數值。
- 二進位制:有字首`0b`或`0B`的數值。
js會自動將八進位制、十六進位制、二進位制轉為十進位制
9. js存在2個`0`:`+0`,`-0`,兩者是等價的。唯一區別是`+0`或`-0`當作分母時表示式的返回值不相等。
10. `NaN`表示“非數字”(`Not a Number`),比如字串解析為數字報錯時會返回`NaN`。0除以0得到NaN。`NaN`只是一個特殊值,型別依舊是`Number`
11. **`NaN`不等於任何值,包括它本身**
```js
NaN === NaN // false
```
`NaN`的布林值為false,`NaN`與任何數(包括它自己)的運算,得到的都是`NaN`
12. `Infinity`表示“無窮”,表示無法表示正無窮(`Infinity`)和負無窮(`-Infinity`);非0數除以0,得到`Infinity`。
`Infinity`大於一切數值(除了`NaN`),`-Infinity`小於一切數值(除了`NaN`)
`NaN`的比較運算會返回false
13. `parseInt()`方法將字串轉為整數。字串轉為整數時,會一個個字元依次轉換,如果遇到不能轉為數字的字元,就不再進行下去,返回已經轉好的部分。轉換失敗返回`NaN`。
解析科學計數法的數字時會出現奇怪的結果
第二個引數表示解析的值的進位制
```js
parseInt('1000', 2) // 8
parseInt('1000', 6) // 216
parseInt('1000', 8) // 512
```
14. `parseFloat()`:將一個字串轉為浮點數,可以對科學計數法字串正確轉換
15. `isNaN()`判斷一個值是否是`NaN`。`isNaN()`只對數值有效,其他型別值會先轉為數值,再判斷。對於空陣列和只有一個數值成員的陣列,`isNaN()`返回false
```js
isNaN('Hello') // true
// 相當於
isNaN(Number('Hello')) // true
```
16. 判斷NaN最好的方法是:**`NaN`是唯一不等於自身的值**
```js
function myIsNaN(value) {
return value !== value;
}
```
如果使用`isNaN()`判斷,要同時判斷型別:
```js
function myIsNaN(value) {
return typeof value === 'number' && isNaN(value);
}
```
17. `isFinite()`判斷是否為正常的數值,判斷是引數也會進行型別轉換
## 字串
1. 字串是放在單引號或雙引號中的零個或多個排在一起的字元。字串中使用相同的引號要用`\`反斜槓轉義
2. 每行的尾部使用反斜槓,可以實現多行字串(`\`後面只能有換行符,否則報錯)
```js
var longString = 'Long \
long \
long \
string';
longString // "Long long long string"
```
也可使用`+`可以將多個字串行連線
3. 反斜槓(`\`)用來表示一些特殊字元,稱為轉義。如`\n`換行符;`\r`:回車鍵;`\t`:製表符。如果在字串中需要包含反斜槓,需要`\`轉義自身。
```js
"你好,反斜槓\\"; // "你好,反斜槓\"
```
4. 字串可以看做字元陣列,但僅能使用陣列的方括號運算子獲取字元,而不能進行其他操作
5. length屬性返回字串長度
```js
'hello'.length // 5
```
6. js使用`Unicode`字符集。不僅以Unicode儲存字元,而且可以只用Unicode碼點,如'\u00A9'表示版權符號
```js
var s = '\u00A9';
s // "©"
```
每個字元在 JavaScript 內部都是以16位(2個位元組)的 `UTF-16` 格式儲存。js單位字元長度固定為16位長度
js 對 `UTF-16` 的支援不完整,只支援兩位元組的字元,無法識別四位元組的字元。比如四位元組字元`