###### tags: `JavaScript`
# JavaScript 基礎篇
## 變數(Variable)與值(Value)
- 宣告變數的方法:let、const、var
- let、const 宣告的變數不會存在於 windows 裡面,使用 this 要注意 [範例](https://codepen.io/nielsen_dch/pen/vYJvYad?editors=1111)。
- 基本型別 ( primitives types ) 介紹
1. 字串 ( String )
2. 數字 ( Number )
3. 布林 ( Boolean )
4. undefined - 尚未被賦予值
5. null - 有被賦予值,但是是空值
6. Symbol
- 型別操作方法
> 除了基本型別外,後面還會講解物件型別,例如陣列(array)與物件(object)
## 比較運算子與邏輯運算子
```javascript=
// 比較運算子 >、=、<=
let a = 1;
let b = 2;
let c = 1;
a < b // true
a > b // false
a >= c // true
a <= c // true
// 比較運算子 ==、===、!=、!==
// == 的時候不會判斷轉型別,所以只要字串內容跟數字是一樣就 true
// ==== 的時候會先判斷轉型別再比較內容,所以只要型別或字串內容不一樣就 false
let a = '1'
let b = 1;
a == b // true
a === b // false
a != b // false
a !== b // true
// 邏輯運算子 &&、||
// 如果有多筆判斷式用 && 代表所有的判斷都要符合
// 如果有多筆判斷式用 || 代表只要有一個符合就好
let a = 1;
let b = 2;
let c = 1;
a === c && b > a // true
a === c && b < a // false
a === c || b === a // true
a === c || b <= a // true
```
# JavaScript 操作語法
## parseInt()字串轉數字
```javascript=
// 轉換型別成功,如果變數開頭是數字後面是字串會取前面的數字
let a = '34';
console.log(typeof a); // string
console.log(typeof parseInt(a)); // number
let b = '50ertyetddgv';
console.log(parseInt(b)); // 50
let c = '0.55';
console.log(parseInt(c)); // 0
// 轉換型別錯誤,如果變數開頭是中英文字或特殊符號會出現 NaN
let d = 'ab34c';
console.log(parseInt(d)); // NaN
let e = '!99';
console.log(parseInt(e)); // NaN
```
---
## toString() 數字轉字串方法
```javascript=
let a = 34;
console.log(typeof a); // number
console.log(typeof a.toString()); // string
let b = 50;
console.log(b.toString()); // "50"
let c = 0.55;
console.log(c.toString()); // "0.55"
```
---
## toLowerCase() 字串轉小寫
```javascript=
const str1 = 'This Is A Apple';
console.log(str1.toLowerCase()) // this is a apple
const str2 = '你好嗎 NICK';
console.log(str2.toLowerCase()) // 你好嗎 nick
const str3 = 'DFGd4eg@112dFHf~fHJTg';
console.log(str3.toLowerCase()) // dfgd4eg@112dfhf~fhjtg
```
---
## toUpperCase() 字串轉大寫
```javascript=
const str1 = 'this is a apple';
console.log(str1.toUpperCase()) // THIS IS A APPLE
const str2 = '你好嗎 Nick';
console.log(str2.toUpperCase()) // 你好嗎 NICK
const str3 = '@2f304ge4hgjur54!';
console.log(str3.toUpperCase()) // @2F304GE4HGJUR54!
```
---

## innerHTML 設定/取得標籤
innerHTML 特性會清空標籤內的內容,在塞入自訂義的內容
```javascript=
<h1 class="titleClass">
<a href="#">title</a>
</h1>
<script>
var el = document.querySelector('.titleClass').innerHTML;
console.log(el); // <a href="#">title</a>
</script>
```
innerHTML 搭配 for 迴圈
```javascript=
<ul class="list"></ul>
<script>
var farms=[
{
farmer:'卡斯柏',
dogs:['張母是','小白'],
},
{
farmer:'老張',
dogs:['欣欣'],
},
]
var el = document.querySelector('.list');
var len = farms.length;
var str = ''; // 累加用
for(var i=0;i<len;i++){
if(farms[i].dogs.length > 1){
var content = `<li>第 ${i + 1} 農場的主人是 ${farms[i].farmer} ,她的寵物有 ${farms[i].dogs.length} 隻,分別叫做 ${farms[i].dogs}</li>`;
}else{
var content = `<li>第 ${i + 1} 農場的主人是 ${farms[i].farmer} ,她的寵物有 ${farms[i].dogs.length} 隻,叫做 ${farms[i].dogs}</li>`;
}
str+=content;
}
el.innerHTML = str;
</script>
```
結果如下
- 第 1 農場的主人是 卡斯柏 ,她的寵物有 2 隻,分別叫做 張母是,小白
- 第 2 農場的主人是 老張 ,她的寵物有 1 隻,叫做 欣欣
---
## createElement 新增 HTML 標籤
```javascript=
<h1 class="title">
<em>title</em>
</h1>
<script>
// createElement() 插入 HTML 標籤
// appendChild 動態插入子節點
var str = document.createElement('em'); // 準備插入 em 標籤
str.textContent = '1234'; // em 標籤內容
// 目前 str = <em>1234</em>
document.querySelector('.title').appendChild(str);
</script>
```
結果如下

createElement 搭配 for 迴圈
```javascript=
<ul class="list"></ul>
<script>
var farms=[
{
farmer:'卡斯柏',
dogs:['張母是','小白'],
},
{
farmer:'老張',
dogs:['欣欣'],
},
]
var el = document.querySelector('.list');
var len = farms.length;
for(var i=0;i<len;i++){
var str = document.createElement('li');
if(farms[i].dogs.length > 1){
str.textContent = `第 ${i + 1} 農場的主人是 ${farms[i].farmer} ,她的寵物有 ${farms[i].dogs.length} 隻,分別叫做 ${farms[i].dogs}`;
}else{
str.textContent = `第 ${i + 1} 農場的主人是 ${farms[i].farmer} ,她的寵物有 ${farms[i].dogs.length} 隻,叫做 ${farms[i].dogs}`;
}
el.appendChild(str);
}
</script>
```
結果如下
- 第 1 農場的主人是 卡斯柏 ,她的寵物有 2 隻,分別叫做 張母是,小白
- 第 2 農場的主人是 老張 ,她的寵物有 1 隻,叫做 欣欣
---
## textContent 設定/取得標籤裡的內容
```javascript=
<h1 class="titleClass">
<a href="#">title</a>
</h1>
<script>
var el = document.querySelector('.titleClass a');
console.log(el.textContent); // title
</script>
```
---
## setAttribute 設定屬性
setAttribute('屬性', '修改成')
> ex: setAttribute('href', 'https://tw.yahoo.com/')
他會將屬性的清空再加入你要修改的值,所以如果是 class 會變成單一個
> 原本:< div class="strId adwd">123456789< /div>
>
> 在 JS 加入:
> var el = document.querySelector('.strId');
> setAttribute('class', 'abc')
>
> 結果:< div class="abc">123456789< /div>
```javascript=
<style>
.strId{
color: red;
}
</style>
<h1 class="titleClass">
<a href="#">title</a>
</h1>
<div class="str">123456789</div>
<script>
var el = document.querySelector('.titleClass a');
var el2 = document.querySelector('.str');
el.setAttribute('href','https://tw.yahoo.com/'); // 修改 a 連結
el2.setAttribute('id','strId'); // 新增 id
</script>
```

---
## getAttribute 取得屬性
getAttribute('屬性')
> ex: getAttribute('href')
```javascript=
<style>
.strId{
color: red;
}
</style>
<h1 class="titleClass">
<a href="https://123.com">title</a>
</h1>
<script>
var el = document.querySelector('.titleClass a').getAttribute('href')
console.log(el) // https://123.com
</script>
```
---
## classList.add() 新增 class
```javascript=
<div id="id" class="a1">請看 class name</div>
<script>
// classList.add 新增
document.getElementById("id").classList.add('a2');
// classList.add 新增多筆
// document.getElementById("id").classList.add('a2', 'a3', 'a4');
</script>
```

---
## classList.remove() 移除 class
```javascript=
<div id="id" class="a1 a2 a3">請看 class name</div>
<script>
// classList.remove 移除
document.getElementById("id").classList.remove('a1');
// classList.remove 移除多筆
// document.getElementById("id").classList.add('a2', 'a3', 'a4');
</script>
```

---
## classList.contains() 判斷 class
```javascript=
<div id="id" class="a1">請看 class name</div>
<script>
// classList.contains 判斷是否有對應的 class
if (document.getElementById("id").classList.contains('a1')){
console.log('Yes');
} else {
console.log('No');
}
</script>
```

---
## classList.toggle() 切換 class
- 沒有 a2 的時候
```javascript=
<div id="id" class="a1">請看 class name</div>
<script>
// classList.toggle 當有對應的 class 就移除,沒有就增加
document.getElementById("id").classList.toggle('a2');
</script>
```

- 有 a2 的時候
```javascript=
<div id="id" class="a1 a2">請看 class name</div>
<script>
// classList.toggle 當有對應的 class 就移除,沒有就增加
document.getElementById("id").classList.toggle('a2');
</script>
```

---
## classList function
```javascript=
<div id="id" class="a1 a3">請看 class name</div
<script>
function hasClass(el, className) {
if (el.classList) {
return el.classList.contains(className);
} else {
return !!el.className.match(new RegExp('(\\s|^)' + className + '(\\s|$)'));
}
}
function addClass(el, className) {
if (el.classList) {
el.classList.add(className);
} else if (!hasClass(el, className)) {
el.className += " " + className;
}
}
function removeClass(el, className) {
if (el.classList) {
el.classList.remove(className);
} else if (hasClass(el, className)) {
var reg = new RegExp('(\\s|^)' + className + '(\\s|$)');
el.className=el.className.replace(reg, ' ');
}
}
let el = document.getElementById('id')
// 新增 a2
addClass(el, 'a2')
// 移除 a3
removeClass(el, 'a3')
// 判斷
console.log(hasClass(el, 'a1')); // true
</script>
```

# JavaScript 函式
## 函式陳述式 & 函式表達式差別
### <font color="#f00">函式陳述式</font> 呼叫的時候可以不用按照順序擺放,因為有提升(Hoisting)所以都可以正常執行
```javascript=1
console.log(numA(2)); // 4
function numA(x){
return x * x;
}
console.log(numA(2)); // 4
```
### <font color="#f00">函式表達式</font> 是將函式賦予到變數上,所以一定要按照程式碼讀取的順序排,不然會出錯
- 錯誤的方式
```javascript=1
console.log(numA(2)); // Identifier 'numA' has already been declared
const numA = function (x){
return x * x;
}
```
- 正確的方式
```javascript=1
const numA = function (x){
return x * x;
}
console.log(numA(2)); // 4
```
## 函式陳述式、函式表達式、箭頭函式使用方式
```javascript=1
// 函式陳述式
function numA(x){
return x * x;
}
// 函式表達式
const numB = function (x){
return x * x;
}
// 箭頭函式
const numC = (x) => {
return x * x;
}
// 箭頭函式縮寫-沒有參數
const numD = () => '沒有參數';
// 箭頭函式縮寫-單一參數
const numE = x => x * x;
// 箭頭函式縮寫-多個參數
const numF = (x,y) => x * y;
console.log(numA(2)); // 4
console.log(numB(2)); // 4
console.log(numC(2)); // 4
console.log(numD()); // 沒有參數
console.log(numE(2)); // 4
console.log(numF(2,3)); // 6
```