# JavaScript
---
由於各位或多或少都已經會程式基礎了
~~上次C#很慘~~
所以我們今天著重在JS的特殊用法~
----
## 在這堂課你會了解到...
* JS Declaration
* Ternary Operator
* Template Strings
* For Iteration
* ... (rest & spread)
↓
----
* Object
* Prototype
* Arrow Function & this
* String & Array Prototype
* ~~Timing Function~~
* ~~Promise & async~~
* ~~JS Fuck~~
----
### 練習環境
[瀏覽器](about:blank) (F12 dev tool)
NodeJS
[Online Compiler](https://codepen.io/) (不推薦)
---
## JS Declaration(JS宣告)
還記得上禮拜C#講的嗎?
由於JS是動態語言,
宣告被簡化成以下三個:
* var
* let
* const
----
### var(全域變數)
存活於function內,
可重複宣告,宣告前存取為undefined
宣告會自動提升(hoisting)到function開頭
```javascript=
...1
var test = "Hi";
...2
var test = "<3";
```
```javascript=
var test;
...1
test = "Hi";
...2
test = "<3";
```
以上兩個相等
----
### let(區域變數)
存活於block內
**不可**重複宣告,宣告前存取Error
```javascript=
console.log(test1);
let test1 = "❓";
// Uncaught ReferenceError: Cannot access 'test1' before initialization
{
let test2 = "😵";
}
console.log(test2);
// Uncaught ReferenceError: test2 is not defined
```
----
### const(區域常數)
等同於let,但**不可再次賦值**
```javascript=
const test3 = "😡";
test3 = "😰";
// Uncaught TypeError: Assignment to constant variable.
```
---
## Operator(運算子)
還記得上次C#的內容嗎?

補充 JS有**(次方運算)
----
### 「===」
由於JS是弱型別語言,
所以我們需要一個比較運算子判斷型態相同
```javascript=
1=="1" // true
1==="1" // false
```
----
### Ternary Operator(三元運算子)
記得if語法嗎?
可以縮寫喔
```javascript=
let a = 1;
if(a==="1")
console.log("是1")
else
console.log("不是1")
```
```javascript=
let a = 1;
console.log((a==="1") ? "是1":"不是1")
```
---
## Template Strings(樣板字串)
你是否有遇過以下狀況?
```javascript=
let year=2222,
month=2,
day=22,
hour=2,
minute=22,
second=22;
console.log("現在時間是: "+year+"/"+month+"/"+day+
" "+hour+":"+minute+":"+second);
// 現在時間是: 2222/2/22 2:22:22
```
想把變數跟字串一起輸出,但一堆+很難看?
----
```javascript=
console.log(`現在時間是: ${year}/${month}/${day} ${hour}:${minute}:${second}`);
```
這樣是不是好看了一點?
並且樣板字串可以跨行
```javascript=
console.log(`1
2
3`);
/*1
2
3*/
```
---
## For Iteration(for迭代)
是否曾經寫過類似的程式?
```javascript=
const data = [18,84,45,36,70,28,61,87];
let count = 0;
for (let i=0; i<data.length; i++)
{
if(data[i]<60) count++;
}
console.log(`有${count}個人不及格😰`);
// 有4個人不及格😰
```
只是想跑一遍data這個Array,
但要寫一大串很麻煩?
----
### 隆重介紹in、of、forEach!
```javascript=
const data = [18,84,45,36,70,28,61,87];
for (let i in data)
{
console.log(i) // 以index迭代
}
for (let v of data)
{
console.log(v) // 以value迭代
}
data.forEach(console.log); // value, index, array
```
大家試試看吧~
---
## ... (Spread)
我想搜尋陣列裡的最小值該怎麼辦?
```javascript=
const data = [18,84,45,36,70,28,61,87];
console.log(Math.min(...data));
// 18
```
```javascript=
console.log(["開頭", ...data, "結尾"]);
// ['開頭', 18, 84, 45, 36, 70, 28, 61, 87, '結尾']
```
使用...可以將Array內的value展開
----
### ... (Rest)
不確定function會輸入幾個參數怎麼辦?
```javascript=
function test1(a, ...input)
{
console.log(a, input);
}
test1(null, true, "ABC"); // null [ true, 'ABC' ]
test1(); // undefined []
test1(1,2,3,4,5,6,7,8,9); // 1 [2, 3, 4, 5, 6, 7, 8, 9]
```
可以將最後一個參數定為Array
要注意的是只能放最後一位
---
## Object
什麼是Object?
在JS裡是字典(dictionary)
{ key1: value1, key2: value2, ... }
```javascript=
const obj = {};
obj["hi"] = true;
obj.hello = "😋";
console.log(obj);
console.log(obj["hello"]);
console.log(obj.hi);
const newObj = {"我是":"新的", ...obj};
console.log(newObj);
```
----
### Prototype(原型)?
簡單來說就是各個Object的共通屬性(通常是function)
```javascript=
console.log(String.prototype == "".__proto__)
// true
console.log("貓該怎麼叫?".meow());
// Uncaught TypeError: "貓該怎麼叫?".meow is not a function
String.prototype.meow = function()
{
return "喵".repeat(this.length);
}
console.log("貓該怎麼叫?".meow());
// 喵喵喵喵喵喵
console.log((123).zero); // undefined
Number.prototype.zero = 0;
console.log((123).zero); // 0
```
---
## what is this?
有注意到上一頁的meow內部有用到this嗎?
那麼什麼是this呢?
簡單來說,this會根據場景回傳當前的Object
```javascript=
console.log(this);
String.prototype.showSelf = function()
{
console.log(this);
}
"你好".showSelf();
```
* 延伸閱讀: [之前學長做的this教學](https://hackmd.io/@happy123/JSthis#/)
----
### Arrow Function
又稱箭頭函式、~~lambda~~
```javascript=
() => {} // 標準格式,return需額外寫
e => {} // 只有一個參數可省略()
(a,b) => a+b // 只有一行可省略{},並return
String.prototype.arrowFunc = ()=>{console.log(this)}
"ABC".arrowFunc();
// 試試看什麼效果?
```
---
## String Prototype
[**Mozilla Wiki**](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)
* at
* indexOf / lastIndexOf
* includes
* padStart / padEnd
* repeat
* replace / replaceAll
----
* split
* substring
* slice
* toLowerCase / toUpperCase
* trim
* trimStart
* trimEnd
----
### at
類似於[],但可使用負數
```javascript=
const s = "ABCDEFG";
console.log(s[1]); // B
console.log(s.at(-6)) // B
```
----
### indexOf
從 string/end 搜尋指定String**位置**,找不到回傳-1
`lastIndexOf` 從end
`includes` 是否包含指定String
```javascript=
const s1 = "ABCDCBA";
console.log(s1.indexOf("B")); // 1
console.log(s1.lastIndexOf("B")); // 5
console.log(s1.includes("CDC")); // true
(s1.indexOf("ABC") != -1)
(s1.includes("ABC"))
// 以上兩行結果相等
```
----
### pad
從 start/end 填補String直到指定長度
```javascript=
const s2 = "ABC";
console.log(s2.padStart(7, "123"));
// 1231ABC
console.log(s2.padEnd(7, "123"));
// ABC1231
```
----
### repeat
重複String指定次數
```javascript=
console.log("123 ".repeat(5));
// 123 123 123 123 123
```
----
### replace
取代String 一次/所有
```javascript=
const s3 = "😠😠😠😠";
console.log(s3.replace("😠", "😡"));
// 😡😠😠😠
console.log(s3.replaceAll("😠", "😡"));
// 😡😡😡😡
```
----
### split
透過指定String分割整個String為Array
```javascript=
const s4 = "123/456/789";
console.log(s4.split("/"));
// ['123', '456', '789']
```
----
### substring
透過索引(index)提取String
`slice` 可為負數
```javascript=
const s5 = "How are you?";
console.log(s5.substring(4, 10));
console.log(s5.slice(-8, -2));
// are yo
```
----
### to...Case
英文轉 大/小 寫
```javascript=
console.log("A".toLowerCase()); // a
console.log("a".toUpperCase()); // A
```
----
### trim
移除頭尾空格、換行字符
可單獨移除start/end
```javascript=
const s6 = "\nABC123 ";
console.log(s6.trim());
console.log(s6.trimStart());
console.log(s6.trimEnd());
```
---
## Array Prototype
[**Mozilla Wiki**](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)
* at
* indexOf / lastIndexOf
* includes
* pop / push
* shift / unshift
* join
* reverse
----
* forEach
* filter
* map
* every / some
* slice
----
### join
將Array元素透過String組合起來
```javascript=
const a1 = [123, 456, 789];
console.log(a1.join("-"));
// 123-456-789
```
----
### reverse
將Array顛倒過來
```javascript=
const a2 = [123, 456, 789];
console.log(a2.reverse());
// [789, 456, 123]
```
----
### forEach
輸入一個function,對每個值做一次
```javascript=
const data = [18,84,45,36,70,28,61,87];
let count = 0;
data.forEach((score) =>
{
if (score<60) count++;
});
console.log(`有${count}個人不及格😰`);
```
----
### filter
輸入一個function,過濾掉false的值
```javascript=
const data = [18,84,45,36,70,28,61,87];
let count = data.filter((score) => score<60).length;
console.log(`有${count}個人不及格😰`);
```
----
### map
輸入一個function,對每個值做一次,
並將return組成一個新Array
```javascript=
const data = [18,84,45,36,70,28,61,87];
let newData = data.map((score) => (score**0.5)*10);
console.log(newData);
```
----
### every / some
輸入一個function,
檢測Array內是否 全部/至少一個 達成條件
```javascript=
const data = [18,84,45,36,70,28,61,87];
console.log("所有人高於10分?",
data.every((score)=>score>10));
console.log("至少一人高於90分?",
data.some((score)=>score>90));
```
----
### slice
擷取Array,可輸入負數
```javascript=
const data = [18,84,45,36,70,28,61,87];
console.log(data.slice(-5, -1));
console.log(data.slice(3, 7));
// [36, 70, 28, 61]
```
---
## Timing Function
```javascript=
setTimeout(fn, ms);
setInterval(fn, ms);
```
---
## Promise & async
```javascript=
const delay = (ms=0) => {return new Promise((rs)=>{setTimeout(rs,ms)})}
(async ()=>
{
let count = 0;
while(true)
{
await delay(1000);
console.log(`Hi, ${++count}`);
}
})()
```
---
## JS Fuck
[fuck](http://www.jsfuck.com/)
```javascript=
(!![]+[])+(![]+[])
// 執行看看?
```
---
# End
{"metaMigratedAt":"2023-06-17T14:43:17.457Z","metaMigratedFrom":"YAML","title":"JavaScript","breaks":true,"contributors":"[{\"id\":\"8416e9d5-bab3-4b78-8d9b-644817bd3d18\",\"add\":9252,\"del\":1143}]"}