# RE:從0開始的JS *Min* --- ## ECMAScript? ---- ECMAScript 是 JavaScript 的標準,目的是讓不同瀏覽器之間能根據 spec 來實作。當 ECMAScript 發布第三版 (即 ES3) 之後,成為當時所有瀏覽器支援的程式語言。 ---- 而各家瀏覽器就會依照ECMAScript的標準,去實作JavaScript的runtime(執行環境)。 ---- 而ECMAScript 會隨著時代演進而更新內容(例如新增語法、功能),所以可能會聽到ES5、ES6之類的,那指的就是ECMAScript的第幾個版本 --- ## NodeJS 是一個可以跑在伺服端的Javascript執行環境,可以讓JS直接在電腦上執行,不用透過瀏覽器。 ---- ### 來下載一下ㄅ ubuntu ```bash curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash - sudo apt-get install -y nodejs ``` [Windows](https://nodejs.org/en/download/) [其他的可以看這裡](https://nodejs.org/zh-tw/download/package-manager/) ---- ### 順便把yarn也裝一裝ㄅ ```bash= # ----ubuntu---- curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add - echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list sudo apt-get install yarn # ----homebrew---- brew install yarn # ----arch---- pacman -S yarn ``` [Windows](https://classic.yarnpkg.com/lang/en/docs/install/#windows-stable) ---- 那該怎麼用呢 ---- 直接node index.js ---- 可以先建一個空白的index.js 然後在裡面輸入console.log("Hello") 接著在終端機下node index.js --- ## 基本語法篇 ---- ## 先從印出東西開始吧 ---- ## console.log() ---- ```javascript= console.log("Hello World") ``` --- ## 變數與資料型別 ---- * var 作用域是「函式(function)」 * let ES6新增的,作用域是「區塊(block)」 * const 用來宣告常數的 ---- 先試試看ㄅ ```javascript= var a = 123; let b = "123"; //盡量用這個 const c = true; //宣告後,就不能再被改了 console.log(a); console.log(b); console.log(c); ``` ---- 變數名稱的限制: 1. 第一個字元必須是字母 (大小寫皆可) 或是底線 (_),之後的字元,可以是數字、字母或底線。 2. 區分大小寫、 var XYZ 並不等於 var xyz。 3. 變數名稱不能用 JavaScript 的保留字。 ---- #### 資料型態 ![](https://i.imgur.com/uSYlnT9.png) ---- #### 動態型別 ```javascript= let a = 123; console.log(typeof a); a = "123"; console.log(typeof a); ``` ---- ### 關係運算子 ![](https://i.imgur.com/piv1BN3.png) ---- ![](https://i.imgur.com/c66VyBK.png) ---- ```javascript= console.log("123" == 123) //true console.log("123" === 123) //false console.log(123 != "123") //false console.log(123 !== "123") //true ``` ![](https://i.imgur.com/SDoZlCV.png) --- ## if...else ---- #### 語法 ```javascript= if (condition1) statement1 else if (condition2) statement2 else if (condition3) statement3 ... else statementN ``` ---- ### 三元運算子 ```javascript= condition ? exprIfTrue : exprIfFalse ``` #### 範例 ```javascript= let a = true ? "apple" : "pineapple"; console.log(a); //apple ``` --- ## for and while ---- ### for迴圈 ```javascript= for (let i = 0; i < 5; i++) { console.log(i); } ``` ### while迴圈 ```javascript= let i = 0; while (i < 5) { console.log(i); i++; } ``` --- ## function ---- ### 語法 ```javascript= // 第一種 function functionName(parameter1, parameter2, ...) { // statements return value; } // 第二種 let functionName = function(parameter1, parameter2, ...) { // statements return value; } ``` ---- ```javascript= // 箭頭函式 let functionName = (parameter1, parameter2, ...) => { // statements return value; } // 如果只有一個參數的話 // 括號可以省略 let functionName = x => { } ``` [延伸閱讀-JS的this](https://blog.techbridge.cc/2019/02/23/javascript-this/) --- ## array ---- ### 語法 ```javascript= let a = ["Apple", "Banana", "Pineapple"]; let b = [1, 2, 3]; let c = [4, "Berry", true]; ``` ---- ### 想把東西丟進去? ```javascript= let a = [1, 2, 3]; // 從尾端 a.push(4) // [1, 2, 3, 4] // 從開頭 a.unshift(5); // [5, 1, 2, 3, 4] ``` ---- ### 那想拿出來呢 ```javascript= let a = [1, 2, 3, 4]; // 從尾端 a.pop() // 4 // 從開頭 a.shift(); // 1 ``` --- ## object ---- ### 語法 ```javascript= let obj = { key1: value1, key2: value2, ... }; ``` ---- ```javascript= let person = { name: "Min", country: "Taiwan", gender: "male", }; // 取得物件裡的值 person.name person["name"] // Min // 修改物件裡的值 person.name = "FKT" person["name"] = "FKT" console.log(person.name) //FKT ``` ---- ```javascript= // 在物件裡新增屬性 person.department = "資管系" person["department"] = "資管系" console.log(person) // { // name: "FKT", // country: "Taiwan", // gender: "male", // department: "資管系", // }; ``` --- ## 進階篇 ---- ## 高階函式 ---- ### forEach ```javascript= const fruits = ['Apple', 'Pineapple', 'Cherry']; // forEach fruits.forEach(function(item) { console.log(item); }); // 等於 for (let i = 0; i < fruits.length; i++) { const item = fruits[i]; console.log(item); } ``` ---- ### map ```javascript= let numList = [1, 2, 3, 4, 5]; // map會回傳一個陣列 let array = numList.map(function (item) { return item + 1; }); // [2, 3, 4, 5, 6] // 等於 let array = []; for (let i = 0; i < numList.length; i++) { const item = numList[i]; array.push(item + 1); } ``` ---- ### filter ```javascript= const words = ["spray", "limit", "elite", "exuberant", "destruction", "present", "happy"]; let longWords = words.filter(word => word.length > 6); // ["exuberant", "destruction", "present"] // 等於 let longWords = []; for (let i = 0; i < words.length; i++){ const word = words[i]; if (word.length > 6){ longWords.push(word); } } ``` --- ## Spread Operator & <br />Rest Operator ---- ### Spread Operator 把一個陣列展開成個別的值的速寫語法 ```javascript= const params = [ "hello", true, 7 ] const other = [ 1, 2, ...params ] // [ 1, 2, "hello", true, 7 ] ``` ```javascript= function sum(a, b, c) { return a + b + c } const args = [1, 2, 3] sum(…args) // 6 ``` ---- ### Rest Operator 收集其餘的(剩餘的)這些值,轉變成一個陣列。它會用在函式定義的傳入參數識別名定義(其餘參數, Rest parameters),以及解構賦值時 ---- ```javascript= function test(...numbers) { console.log(numbers) } test(1) // [1] test(1, 2, 3, 4, 5) // [1, 2, 3, 4, 5] function aFunc(x, ...y){ console.log('x =', x, ', y = ' , y) } aFunc(1,2,3) //x = 1, y = [2, 3] aFunc() //x = undefined, y = [] ``` 其餘參數在傳入參數定義中,只能位於最後一位, 並且在參數中只能有一個其餘參數。 --- ## 解構賦值 ---- ### 陣列解構 ```javascript= const x = [1, 2, 3, 4, 5]; const [y, z] = x; console.log(y); // 1 console.log(z); // 2 // 結合rest operator [a, b, ...rest] = [10, 20, 30, 40, 50]; console.log(a); // 10 console.log(b); // 20 console.log(rest); // [30, 40, 50] ``` ---- ### 物件解構 ```javascript= const person = { name: "Min", studentID: "B10923012", skills: { frontend: ["HTML", "JS", "CSS"], backend: ["flask", "express", "docker"] } }; const { studentID } = person; // "B10923012" const { skills: { frontend } } = person; // ["HTML", "JS", "CSS"] ``` --- ## 模板語法 ---- ### 語法 用「\`」括起來,就可以使用 ${...} 來加入變數或函式 ```javascript= let firstName = "John"; let lastName = "Doe"; let text = `Welcome ${firstName}, ${lastName}!`; ``` --- ## 補充說明 這部分可以先跳過,有興趣再聽,後面有練習題可以先寫 ---- ## var && let 前面說過var的作用域是函式(function),而let是區塊(block)。 那作用域到底是什麼呢 ---- ```javascript= { // block var a = "apple"; let b = "banana"; console.log(a); // apple console.log(b); // banana } console.log(a); // apple console.log(b); // ReferenceError: b is not defined ``` ---- ```javascript= // var function varTest(){ var i = "Hello World" console.log(i) // "Hello World" } console.log(i); //ReferenceError: i is not defined // let function letTest() { let j = "Hello World" console.log(j) // "Hello World" } console .log(j) //ReferenceError: j is not defined ``` ---- ### var可以被重複宣告,let會報錯 ```javascript= var a = "123" var a = "456" let b = "123" let b = "456" //SyntaxError: Identifier 'b' has already been declared ``` ---- ### hoisting(提升)? ---- 如果我們試圖對未宣告的變數取值,node會報錯 ```javascript= console.log(a) // ReferenceError: x is not defined ``` ---- 那如果我們在使用後再宣告呢 ```javascript= console.log(b) //猜猜看結果 var b = 123 console.log(b) //猜猜看結果 ``` ---- ### Answer: * undefined * 123 ---- 在 JavaScript 中,不管你在函數中的哪一行用 var 宣告變數,一律視為在函數的第一行宣告,這個行為就叫做hoisting(提升)。 要注意的是,只有「宣告」這個動作有 hoisting 的特性,賦值 (把值指定給變數) 的動作不會 hoisting。 ---- 所以剛剛的範例可以看成這樣 ```javascript= var b; console.log(b); b = 123; console.log(b); ``` ---- 在let裡就有點不一樣了 似乎let不會hoisting...嗎 ```javascript= console.log(b); //ReferenceError: Cannot access 'b' before initialization let b = 123; console.log(b); ``` ---- ### 嗯? ```javascript= let x = "outer value"; { console.log(x); //ReferenceError: Cannot access 'x' before initialization let x = "inner value"; } ``` ---- ### TDZ(暫時死區) let/const 中也存在變數提升的,但是他還有另一個概念「暫時死區」,也就是如果在宣告變數之前使用變數,這個變數就是存在「暫時死區」中無法存取!這時候使用它就會報錯 ReferenceError。 ---- ## 懶人包 ![](https://i.imgur.com/v9SHWgQ.png) --- ### 最後ㄉ小練習 [遊戲機制](https://moored-espadrille-379.notion.site/8c99f1cfcdc943d79e3d0b6dff217ab8) 小天玩射擊遊戲,原本積分 7000 分,他想知道經過今天對戰後最後總積分多少, 但是只知道小天今天戰績(名次,擊殺數): (13,1), (1,8), (2,5), (4,3), (1,6) ---- 1. 協助小天依照表格(遊戲機制說明),使用 calcScore 函式計算每一場取得的分數 calcScore(13,1) -> 10 calcScore(1,8) -> ? calcScore(2,5) -> ? calcScore(4,3) -> ? calcScore(1,6) -> ? 2. 印出文字 "總共對戰 ... 次,目前總分 ... 分,最後一場排名第 ... 名。" ---- ### 附上我寫的範例 ```javascript= let allScore = 7000; //初始分數 // 戰績 let records = [ { rank: 13, kill: 1 }, { rank: 1, kill: 8 }, { rank: 2, kill: 5 }, { rank: 4, kill: 3 }, { rank: 1, kill: 6 } ]; function calcScore({ rank, kill }) { //用解構賦值拿出rank跟kill //如果人數大於6則以6計算 const maxKill = kill > 6 ? 6 : kill; // 基本的分數加成 let bonus = 10; if (rank === 1) { bonus = 25; } else if (rank === 2 || rank === 3) { bonus = 20; } else if (rank === 4 || rank === 5) { bonus = 15; } else if (rank >= 6 && rank <= 10) { bonus = 12; } // 算出得分 return maxKill * bonus; } for (let i = 0; i < records.length; i++) { // 計算分數並加上 allScore += calcScore(records[i]); } console.log( `總共對戰 ${records.length} 次,目前總分 ${allScore} 分,最後一場排名第 ${records[records.length - 1]["rank"]} 名。` ); ``` --- ## 延伸閱讀 [重新認識 JavaScript](https://ithelp.ithome.com.tw/users/20065504/ironman/1259) [JS模組化](https://eyesofkids.gitbooks.io/javascript-start-from-es6/content/part4/module_system.html) [NodeJS入門](https://ithelp.ithome.com.tw/users/20103526/ironman/1081) --- ## 結束~~~ 記得禮拜五18:00-18:30在茶道教室(GA242)集合ㄛ
{"metaMigratedAt":"2023-06-16T15:52:32.559Z","metaMigratedFrom":"YAML","title":"RE:從0開始的JS","breaks":true,"slideOptions":"{\"transition\":\"slide\"}","contributors":"[{\"id\":\"cfefc38e-571b-4baa-8dd1-9a75490e7f5f\",\"add\":11572,\"del\":1782}]"}
    496 views