# JavaScript
[TOC]
HEEEEELLLO
## JavaScript 簡介
- JavaScript 和 JAVA 之間的關係?
- 寫一些簡介.....
## 基礎語法
### 撰寫一個 HelloWorld
- JS 語法是從上到下,依序執行。
```htmlembedded
<script text="text/javascript">
// 控制器彈出一個警告框
alert("這是一個警告彈窗。");
// 向控制台輸出一個內容
console.log("這是一串在控制台輸出的文字。")
// 讓計算機在頁面輸出一個內容
document.write("這是一串在頁面中輸出的文字。")
</script>
```

### JS 的編寫位置
JS的代碼編寫主要有四種方式
**第一種:** 寫在onclick屬性之中 [不推薦]
```htmlmixed
<button onclick="alert('按鈕被點擊了!')">點我一下</button>
```
**第二種:** 寫在href屬性之中 [不推薦]
```htmlmixed
<a href="javascript:alert('按鈕被點擊了!')">點我一下</a>
```
第一、二種方式,不方便維護
**第三種:** 引用 外部 JS 文件 [推薦使用方式]
在 HTML 語法中,插入外部 JS文件
```htmlmixed
<script text="text/javascript" src="/path/script.js"></script>
```
**第四種:** 在內部script1標籤內撰寫JS代碼
```htmlembedded
<script text="text/javascript">
// JS 代碼撰寫的地方
</script>
```
### JS 註釋
要養好一個註釋的習慣,也可以通過註釋來協助編寫代碼。
(把一些代碼註釋掉,觀察結果)
**多行註釋:**
```javascript
/*
* 多行註釋
* /
```
**單行註釋:**
```javascript
// 單行註釋
```
### JS 代碼的一些規定
1. 嚴格區分大小寫
Alert("Hello World"); [錯誤]
alert("Hello World"); [正確]
2. 每一條指令以 ";" 分號作為結尾。當然也可以不填寫,瀏覽器會自動添加,但是這樣會造成系統資源浪費。
3. JS會自動忽略換行跟空格,所以可以利用空格跟換行讓代碼更整潔。
### 字面量與變量
1. 字面量是不可改變的值。例如: 1,2,3,4, "String",但我們一般不使用字面量,因為沒有任何意義。
2. 變量可以用來保存字面量,變量中的值,可以被任意改變。 例如: X = 5; X = 25;
3. 在js中用 var 來聲明變量。 var x; console.log(x);
(如果沒有聲明,直接使用未宣告變量,會導致error)
4. 聲明和賦值可以同時執行。 var x = 153;
5. 變量的命名盡量要有意義。例如 age = 12 等等
### 變量的命名規則
1. 標示符可以含有字母、數字、_、$。
2. 標示符不可以用數字開頭。
3. 標示符不能是 JS 中的關鍵字或保留字。 例如: var、if、else、console...。
4. 標示符一般採用駝峰命名法(首字母小寫,每個單詞開頭大寫,其餘小寫)。例如: helloWorld。
5. 底層保存標示符號採用 Unicode 編碼 (utf-8)。但盡量不要用英文以外的來命名。
### 六種數據類型
1. 數據類型指的是字面量的類型。
2. JS中一共有六種數據類型
3. String 字串,使用單雙引號包住。例子: "這是一個字符串",單雙引號可以混著用。(其餘規則跟字串使用一樣)
4. Number 數值。
5. Boolean 布爾值。只有兩個[真]true [假]false,用於邏輯判斷使用。
6. Null 專門表示空的對象,typeof會返回object。
7. Undefined 未定義。聲明一個變量不給值,會是Undefined。
8. Object 物件
9. 其中 Object 是引用數據類型,其餘為基本數據類型。
10. 檢查類型指令: typeof 變數名稱
11. JS 中的最大值: Number.MAX_VALUE。
12. Infinity: 無窮值。
13. NaN: Not a number 是一種特殊數字。
14. JS中的數值運算不是一個精確值,會得到部精確的結果。(JS不好解決)
<!-- 閱讀範圍: 尚硅谷 教學 2-10 -->
### JS 語句 statement
==重點筆記==
* 程序是由一條一條的語句所構成。
* 程式中的的語句默認是由上而下,依序執行
* JS 中使用 {} 來對語句進行分組。
* 同一個 {} 被稱為一組語句,或一個代碼塊。
* JS中的代碼塊只有 **分組** 的作用,沒有其他用途。
```javascript
{
alert("....");
console.log("...")
} # 代碼塊
```
**參考視頻** [27 尚硅谷 JS基础 代码块](https://www.youtube.com/watch?v=vted64Bv5Qs&list=PLmOn9nNkQxJFubqN777c_nScnJ4dpEYMT&index=27)
---------------------------
## 流程控制語句
* JS的程序是由上而下依序執行
* 通過流程控制可以控制程序執行的流程
* 使程序可以根據條件選擇執行
### if 語句
* 在執行語句前進行某些判斷。如果成立就執行,不成立反之。
```javascript!
if(條件){
// 如果條件判斷為 TRUE,進入代碼塊執行功能
codes...
}
```
### if...else...
* 如果條件為 true 執行 if 的代碼塊,false 則執行 else
```javascript!
if(條件){
// 如果條件判斷為 TRUE,進入代碼塊執行功能
code1...
}else{
// 如果條件判斷為 FALSE,進入代碼塊執行功能
code2...
}
```
### if...else if...else
* 多個條件判斷可以使用 else if
* 由上而下依序執行條件判斷
* 如果全部條件都不滿足,則執行else
```javascript!
if(條件1){
code1...
}else if (條件2){
code2...
}else if (條件3){
code3...
}else{
code4...
}
```
### switch
* 條件分支語句
* 在執行時,switch後的條件表達式回和case中的數值做全等比較。
* 如果比較結果為 false,向下比較。
* 如果比較結果為 true,則開始執行case底下的代碼。完畢後向下繼續判斷。
* 加入 break,可以在判斷成立後終止判斷。
* 如果所有判斷結果都為 false,則執行 default。
```javascript!
swith(num1){
case 表達式:
code...;
break;
case 表達式:
code2...;
break;
default:
code3...;
break;
}
```
**參考視頻**
[28 尚硅谷 JS基础 if语句(一) - YouTube](https://www.youtube.com/watch?v=e6whBhYJ0SE&list=PLmOn9nNkQxJFubqN777c_nScnJ4dpEYMT&index=28)
[29 尚硅谷 JS基础 if语句(二) - YouTube](https://www.youtube.com/watch?v=eQmU1V_gdXc&list=PLmOn9nNkQxJFubqN777c_nScnJ4dpEYMT&index=29)
[33 尚硅谷 JS基础 条件分支语句 - YouTube](https://www.youtube.com/watch?v=yBORt9P6sdE&list=PLmOn9nNkQxJFubqN777c_nScnJ4dpEYMT&index=33)
---
## 迴圈與循環
### for 迴圈
### while 迴圈 (無窮循環)
### 巢狀迴圈 (大陸用語:嵌套)
### break 和 continue
---
## Object 物件的操作
### 簡介
* 大陸的用語是**對象**,台灣的用語是**物件**
### 物件的方法
> [color=#ff42dc] 學習完函數,才會理解對象中的方法。
```javascript!
// 創建一個對象
var obj = new Object();
obj.name = "王大明";
obj.sayName = function(){
console.log(obj.name)
}
// 調用對象中的函數
obj.sayName(); // 調方法
// 函數也可以作為對象中的屬性
// 如果函數作為一個對象屬性保存,此時,此函數被稱為物件的方法
// 調用函數被稱為,調用物件的方法
document.write(); // 這個是調用 document object 的方法
// 其他撰寫物件方法
var obj2 = {
name: "王大明",
age: 18,
sayName: function(){
console.log(obj2.name)
}
}
```
枚舉物件中的屬性
```javascript!
// for 會枚舉物件中的所有屬性
// n 會是 "name"、"age"、"sayName"
for(var 變量n in 對象obj2){
console.log(n);
// 取值
console.log(obj2[n]);
}
```
==重點筆記==
* 函數可以作為物件的屬性
* 此屬性稱之前物件的**方法**
* 調用物件的方法就是調用物件之中的函數
* 物件有兩種寫法。因此,有兩種方法撰寫方式。
**參考視頻** [57 尚硅谷 JS基础 方法](https://www.youtube.com/watch?v=EZrQo8s2QfM&list=PLmOn9nNkQxJFubqN777c_nScnJ4dpEYMT&index=57)
---
## 函數式 Function
:::info
### 簡介
* 函數也是一個==物件==。
* 函數可以用來封裝一些功能(代碼),必要的時候可以拿來使用。
* 函數可以儲存一些代碼。
> [color=#ff42dc] 說明: 撰寫函數可以避免代碼複用,導致程式碼攏長。
:::
```javascript!
// 創建一個函數物件
var fun = new Function();
console.log(fun); //回傳 空的 function
console.log(typeof fun); //回傳 function
// 封裝到函數中的代碼,不會立即執行,函數中的代碼,會在函數調用的時候執行
var fun = new Function("console.log('This is my first function.')");
//調用函數的語法,調用後,函數內的代碼會按造順序執行
fun();
// 函數就是一個物件,可以有物件的功能
fun.hello = "你好";
console.log(fun.hello);
```
通常不會使用以上的方式定義函數,會用下面方式
```javascript!
// 語法
function FunctionName([para1,para2,...,paraN]){
// js code, you can write mutiple codes here...
alert("!!!!")
console.log("~~V~~")
}
// 調用
FunctionName();
// 匿名函數方法 (效果和上面一樣,兩種都會用到)
// 用賦值語句的方式讓匿名函數被一個變數接住
var fun2 = function(){
....
}
```
**參考視頻** [51 尚硅谷 JS基础 函数的简介](https://www.youtube.com/watch?v=pFQPa-1BqNc&list=PLmOn9nNkQxJFubqN777c_nScnJ4dpEYMT&index=51)
### 函數的參數
```javascript!
// 函數的() 框框中可以傳遞參數
// 可以指定一個或多個形式參數(形參)
// 聲明後並不賦值
function sum(num1,num2){
console.log(num1+num2)
};
// 可以在調用函數時在 ()指定實際參數(實參)
sum(5,3); // 5 對應 num1, 3 對應 num2
// 調用函數的時候,解析器不會檢查 (這個就是 JS 缺點)
sum("string",5)
// 多餘的實參不會賦值,多餘的對應的形參就是 undefined
sum("string",5,23,51,22)
```
**參考視頻** [52 尚硅谷 JS基础 函数的参数](https://www.youtube.com/watch?v=wtGopoF9Jwk&list=PLmOn9nNkQxJFubqN777c_nScnJ4dpEYMT&index=52)
多個變量打包傳入
```javascript!
// 將參數封裝在對象中
var obj = {
name:"王大明",
age: 18,
gender: "男"
}
function sayHello(o){
console.log("你好" + o.name, "今年" + o.age + "。我是" + o.gender + "生")
}
```
函數可以作為參數傳入
```javascript!
function fun(a){
console.log(a)
}
fun(function(){})
```
**參考視頻** [54 尚硅谷 JS基础 实参可以是任何值](https://www.youtube.com/watch?v=yyAloB7_gqI&list=PLmOn9nNkQxJFubqN777c_nScnJ4dpEYMT&index=54)
==重點筆記==
* 參數可以放入任何類型的值。
* 參數可以是物件也可以是函數。
### 函數的返回值
```javascript!
// 創建一個函數計算三數合
// 計算完的東西想給其他功能使用,必須得傳出
// 可以用 ruturn 去接計算結果
function sum(a,b,c){
console.log(a+b+c)
var d = a+b+c;
return d; // 如果不寫 return,返回就會是 undefined
}
// 調用函數,用變數去接
// 函數返回什麼,result 就會是什麼
var result = sum(1,2,3)
```
```javascript!
// 回傳一個 function
function fun3(){
function fun4(){
alert("fun4");
};
// 函數對象作為返回值
return fun4();
}
```
==重點筆記==
* 撰寫 return 可以回傳 function 計算結果。
* return 可以是任意類型的值,string, number, etc...。
* 如果在function中不寫 return,回傳會是一個 **undefined**。
* return 可以是一個 object,也可以是函數。
**參考視頻** [53 尚硅谷 JS基础 函数的返回值](https://www.youtube.com/watch?v=uv76A71htKs&list=PLmOn9nNkQxJFubqN777c_nScnJ4dpEYMT&index=53)
**參考視頻** [55 尚硅谷 JS基础 返回值的类型](https://www.youtube.com/watch?v=xUUw0rvdmq4&list=PLmOn9nNkQxJFubqN777c_nScnJ4dpEYMT&index=55)
### 立即執行函數
```javascript!
// 函數寫完,立即調用,用誇號包住匿名函數
// 函數只會執行一次
(function(){
console.log("Hello")
})();
```
**參考視頻** [56 尚硅谷 JS基础 立即执行函数](https://www.youtube.com/watch?v=_oRaYVoi7Es&list=PLmOn9nNkQxJFubqN777c_nScnJ4dpEYMT&index=56)
### THIS 概念
==重點整理==
* 每次調用函數用函數的時候,都會傳遞一個隱含的參數
* 此隱含參數就是 this, this 指向一個對象
* 這個對象稱為函數執行的上下文對象
* 根據函數調用方式不同,會指向不同的對象
1. 調用函數型式,this 永遠是 window
2. 調用方法形式,this 就是方法的對象
```javascript!
function fun(){
console.log(this.name); // 此時是 window
};
fun(); // 函數形式調用
// 上面的調用等同於, window.fun()
var obj = {
name: "王大明",
sayNmae: fun
}
console.log(obj.sayName == fun); // true
obj.sayName(); // // 方法形式調用,此時是 object [obj]
```
**參考視頻** [61 尚硅谷 JS基础 this](https://www.youtube.com/watch?v=OyM9G71maw4&list=PLmOn9nNkQxJFubqN777c_nScnJ4dpEYMT&index=61)
### 函數的方法 call 及 apply
:::spoiler
123456
:::
---
## 數組 (Array)
:::info
### 簡介
* 內建對象: 包含 object、function
* 數組也是一個對象,他和普通對象(object)功能類似,用來存儲數據。
* 普通對象用字串符作為屬性名 (ex. obj.name)。
* 數組以**數字** 作為索引來操作元素。
* 索引: 從 0 開始。
* 數組儲存的效能比對象好
:::
普通物件
| 屬姓名 | 屬性值 |
| ------ | ------- |
| name | Mr.John |
| age | 15 |
| address | taipei |
數組物件
| index | value |
| ----- | ----- |
| 0 | text1 |
| 1 | text2 |
| 2 | text3 |
創建數組對象
```javascript!
var arr = new Array();
console.log(typeof arr); // 回傳 object
// 添加元素
// 語法: arr[index] = value
arr[0] = "text1";
arr[1] = "text2";
arr[2] = "text3";
// 讀取數組中的元素
// 語法: arr[index]
console.log(arr[0])
console.log(arr[3]) // 讀取不存在的索引,不報錯,返回 undefinded
// 獲取數組長度
// arr 中有一個方法可以調用
console.log(arr.length);
arr[10] = "text10";
// 非連續數組,會獲取最大索引 + 1, 上面的 length = 11
console.log(arr); // 他會給你 text1,text2,text3,,,,,,,,text10
// 盡量不要寫非連續數組
// 修改 arr.length,會刪除多餘元素
arr.legth = 4;
// 往最後位置添加元素的方法
// 語法: 數組[數組.length] = value
arr[arr.length] = "value"
```
==重點整理==
1. Array 可以調用 length 方法。獲取數組的長度
2. 長度會受到非連續數組影響,盡量不要使用非連續數組
**參考視頻** [70 尚硅谷 JS基础 数组简介](https://www.youtube.com/watch?v=uLnNmJcVfUk&list=PLmOn9nNkQxJFubqN777c_nScnJ4dpEYMT&index=70)
### 數組字面量
使用字面量的方式創建數組
```javascript!
// 語法: []
var arr = [];
// 使用字面量創建數組時,可以在創建時就指定元素
var arr2 = [1,2,3,4,5]
// 使用構造函數創建數組時,可以同時添加元素
var arr2 = new Array(10,23,44);
// 創建一個數組,只有一個元素
var arr3 = new Array(10);
// 這時候會生成一個長度為10的數組
// 元素是函數、物件
var arr4 = [function(){console.log}, {"name":"John"}]
```
==重點筆記==
1. 創建數組有不同方式
2. 數組內可以是任何類型的元素、數組、函數,也可以是物件
**參考視頻** [71 尚硅谷 JS基础 数组字面量](https://www.youtube.com/watch?v=XU1RyQ4nseI&list=PLmOn9nNkQxJFubqN777c_nScnJ4dpEYMT&index=71)
### 數組常用的四個方法
1. arr.push(元素1,元素2...): 在數組的**末尾**添加一個或多個元素,返回數組的新長度。
2. arr.pop(): 刪除數組最後一個元素並返回數組的最後一個元素。
3. arr.unshift(元素1,元素2...): 在數組的**開頭**添加一個或多個元素,返回數組的新長度。
4. arr.shift(): 刪除數組第一個元素,並返回數組的第一個元素。
**參考視頻** [72 尚硅谷 JS基础 数组的四个方法](https://www.youtube.com/watch?v=XdOVZZx4cFw&list=PLmOn9nNkQxJFubqN777c_nScnJ4dpEYMT&index=72)
### 數組的遍歷
```javascript!
// 讀取
var arr = [...];
for(var i=0; i<arr.length; i++){
console.log(arr[i])
}
```
### forEach語法
* 一般使用for循環來遍歷數組
* JS 提供一個方法 forEach
* forEach 只有支持 IE8 以上
* 需要一個函數作為參數傳入
* 這種函數,由我們創建,但不由我們調用,稱為**回調函數**。
* 數組有幾個元素,函數執行幾次,每次執行時,會將遍歷的元素,會當實參傳遞進去函數。可以定義形參來讀取。
```javascript!
// 讀取
var arr = [...];
arr.forEach(function(value,index,object){
console.log(value)
})
```
### slice及splice
1. arr.slice(start,end): 從已有的數組返回選定的元素。
start: 開始位置的索引, end: 結束位置的索引。不會改變原本的數組。
2. arr.splice(start,數量,新插入的值1,新插入的值2...): 從已有的數組返回選定的元素進行刪除。會對原本數組要成影響。第三個參數可以傳入新的函數。
### 數組去除重複
```javascript!
var arr = [1,1,2,2,2,4,5,5,2,6,6,9]
for(var i=0; i<arr.length; i++){
console.log(arr[i])
// 從下一個開始比,當前元素後面的所有元素
for (var j=i+1; j<arr.length; j++){
console.log("---->",arr[j])
// 判斷 arr[i] arr[j] 是否相等
if(arr[i]==arr[j]){
// 出現重複函數,則刪除 j
arr.splice(j,1)
// 刪除後,後面的元素會自動補位,往前移動得數字就不會比到
j--; // 再比一次
}
}
}
console.log(arr)
```
### 數組的剩餘方法
1. var arr3 = arr.concat(arr2): 連接兩個數組,將新的數組返回,該方法不會影響原數組。
2. var result = arr.join("-") : 該方法可以將數組轉換為一個字符串,該方法不會影響原數組。 * 類似python中 "".join(list) 方法。默認","。
3. arr.reverse(): 可以反轉數組,會影響原數組。
4. arr.sort(): 排序原本數組,會影響原數組。默認 unicode 排序。如果arr中是數字,還是以 unicode排序,會是錯誤的結果。
```javascript!
// sort 可以傳入參數去定義排序規則
// 需要傳入兩個形參
// 瀏覽器會分別使用數組中的元素作為實參去調用回調函數
// 使用哪個元素調用不確定,但 a 一定再 b 前面
// 瀏覽器根據回掉函數的返回值,決定順序, 返回 > 0,元素會交換
// 瀏覽器根據回掉函數的返回值,決定順序, 返回 < 0,元素不會交換
// 瀏覽器根據回掉函數的返回值,決定順序, 返回 = 0,認為兩個元素相等,也不會交換
arr = [5,4]
arr.sort(function(a,b){
// 前面比後面大,換位
if (a > b){
return 1
// 後面比前面大,不換位
}else if (a < b){
return -1
}else {
return 0 // 數字相等
}
})
arr.sort(function(a,b){
return a - b
// 前面值比後面值大,會是正數,交換位置
// 前面值比後面值小,會是負數,不交換位置
// 前面值比後面值相同,會是0,不交換數字
})
```
**參考視頻** [78 尚硅谷 JS基础 数组的剩余方法](https://www.youtube.com/watch?v=cWuqNdzYnG0&list=PLmOn9nNkQxJFubqN777c_nScnJ4dpEYMT&index=78)
---
## JavaScript 操作 HTML 元件的方式
:::info
### DOM 簡介
* DOM 是 Document Object Model 的縮寫。
* JS 通常是通過 DOM 對於 HTML 文檔進行操作。
* Document 文檔: 表示 HTML網頁文檔。
* 對象: 網頁上面的每一個部分(網頁上的每一個東西)都轉換為一個對象。
* 模型: 表示對象之間的關係,方便我們獲取、操作對象。
* 操作DOM: JS通過操作網頁上的對象,影響HTML的呈現。
:::
### 模型
以下是一個常見的 HTML文檔
```htmlmixed!
<html>
<head>
<title>網頁的標題</title>
</head>
<body>
<a href="xxx.html">超連結</a>
</body>
</html>
```
模型體現出節點與節點之間的關係,有父子、祖先的關係。
```mermaid
graph TD;
文檔-->html;
html-->head;
html-->body;
head-->title;
body-->a;
a-->文本節點;
title-->文本節點;
```
==重點筆記==
* html 中的元件彼此是有關係的。
* 節點 Node 是網頁的基本組成成分。
* html 中的每個部分,標籤、文本、註釋、整個文檔,都是節點。
### 節點的類型
雖然說,網頁中的每個部份,都是結點。但是他們的具體類型是不同的。節點不同,屬性方法也不同。常用的節點分成四類:
1. 文檔節點: 整個 HTML 文檔
2. 元素節點: HTML 文檔 中的 HTML 標籤
3. 屬性節點: 元素的屬性
4. 文本節點: HTML標籤中的文本內容
:::danger
還沒閱讀完畢...
:::
**參考視頻** [91 尚硅谷 JS基础 DOM简介](https://www.youtube.com/watch?v=3D-3Bp7OvOE&list=PLmOn9nNkQxJFubqN777c_nScnJ4dpEYMT&index=91)