JS === ## JS簡介 > - 最初為了解決表單的驗證 (當時網速慢,接送服務器的資料很久) > - 模擬網速工具 > - 這東西可以模擬網速快慢的樣子 > <img src="https://i.imgur.com/ZqMUVTv.png" style="width: 300px;"/> <img src="https://i.imgur.com/Q3pAMom.png" style="width: 100px;"/> > - Netscape 為了避免用戶沒有輸入資料就送出而等很久,想在客戶端驗證資料有無輸入而開發了LiveScript > - 後來與Sun合作,將其改名為JavaScript,以利推廣(Java市佔高),兩者是不同的東西 > - Java: 服務器的編程語言 > - JavaScript: 客戶端的編程語言 ## JS組成 > - [ECMAScript](https://zh.wikipedia.org/wiki/ECMAScript) > - 一開始有Netscape的JS,後來微軟也寫了一個JScript,造成支援的困擾 > - [ECMA International](https://zh.wikipedia.org/wiki/Ecma%E5%9B%BD%E9%99%85)(European Computer Manufacturers Association, 歐洲電腦製造商協會) 訂立了一套ECMAScript標準 > - [BOM](https://zh.wikipedia.org/zh-tw/%E6%B5%8F%E8%A7%88%E5%99%A8%E5%AF%B9%E8%B1%A1%E6%A8%A1%E5%9E%8B) > - [DOM](https://zh.wikipedia.org/wiki/%E6%96%87%E6%A1%A3%E5%AF%B9%E8%B1%A1%E6%A8%A1%E5%9E%8B) ## 引入方式 ### 行內 ```htmlmixed= <body> <input type="button" onclick="alert('GodJJ')"/> </body> ``` ### 寫在 \<script> 內 ```htmlmixed= <head> <meta charset="utf-8"> <script> alert('5566'); </script> </head> ``` ### 外嵌 ```htmlmixed= <head> <meta charset="utf-8"> <script src="test.js"></script> </head> ``` ```javascript= alert('I sad.'); ``` > - 引入的標籤內不要再寫JS Code,不會執行 ## 變量 (variable) > - 程序運行中,會把臨時數據存到記憶體中 > - 變量就是記憶體的標示符,根據變量名可以獲取記憶體存儲的數據 ### 使用變量 > - 聲明變量並附值 ```javascript var num1 = 3; console.log(num1); // 就是一般func調用, 暫略解釋 ``` ```javascript // js的註釋 var str1 = 'GoGoRo'; // str要用引號框起來, 為了跟css區分(""), 所以常用'' console.log(str1); ``` > - 先聲明,後附值 ```javascript var num1; num1 = 3; console.log(num1) ``` > - 同時聲明多個變量並附值 ```javascript var str1 = 'haha', num1 = 5566; // console.log(str1) // console.log(num1) console.log(str1, num1) ``` > - 同時聲明多個變量,後附值 ```javascript var str1, num1 str1 = 'haha' num1 = 5566 console.log(str1, num1) ``` ### 變量命名 > - 規則 > - 由==字母==, ==數字==, ==_==, ==$== 組成 > - ``` > > var num^ = 3 > < Unexpected token '^' > ``` > - 不能由數字開頭 > - ``` > > var 1num = 1 > < Invalid or unexpected token > ``` > - 不能是保留字, 例如 while, for, class > - ``` > > var while = 1; > < Unexpected token 'while' > > > var for = 1; > < Unexpected token 'for' > ``` > - 變量名區分大小寫 > - ``` > > var num = 7 > < undefined > > > num > < 7 > > Num > x Num is not defined at <anonymous>:1:1 > ``` > - 規範(非硬性) > - 駝峰命名 > - 變量名有意義 ## 註釋 > - 單行註釋 > `// xxx` > - 多行註釋 > ``` > /* > xxxxx > xxxxx > */ > ``` ## JS 數據類型 > - JS屬於弱類型語言, 亦即在source code時不用先定義類型 ```javascript= var num1 = 1; // 書寫時沒有定義類型, // 待CPU執行該語句時, 存儲在記憶體的數據才有類型 // c 語言定義變量,書寫時就要定義類型 // int num1 = 1 ``` ### Number > - 進制 ```javascript= // 八進制 0~7 var num = 010 // undefined num // 8 // 如果出現超過8的值, 則會忽略0來當成十進制看待 var num = 018 // undefined num // 18 > 十進制 // 十進制 0~9 var num = 10 // undefined num // 10 // 十六進制 0~9 A~F var num = 0xA undefined num // 10 ``` > - 浮點數 > - 延伸研究 Keyword: > - IEEE-754 > - 浮點數轉二進制 ```javascript= // 科學記數法 var i = 1e-2 // undefined // 1*10^-2 num // 0.01 // ps. 1e+2 = 100 = 1*10^2 // 浮點數誤差 /*簡單說就是由於浮點數有時候很難很完美的轉二進制, 就好像1/3一樣 當設置位數上限時(精度),就會不精確,就好像 0.33不完全等於1/3一樣 所以浮點數運算時有時會有誤差 */ // ps. JS 精度為 17 位小數 0.1+0.2 // 0.30000000000000004 1-0.9 // 0.09999999999999998 1-0.7 // 0.30000000000000004 ``` > - 特殊數值 ```javascript= // MAX_VALUE : 電腦可以存儲的最大值 var num = Number.MAX_VALUE // undefined num // 1.7976931348623157e+308 // MIN_VALUE Number.MIN_VALUE // 5e-324 // Infinity : 無限大 // -Infinity : 無限小 ``` > - 數值檢測 - NaN: Not a number - isNaN: is not a number ```javascript= a = 100 // 100 isNaN(a) // false > a 是否不是一個數字?False a = 'haha' // "haha" isNaN(a) // true > a 是否不是一個數字? True ``` ### String `'abc'` `"abc"` > - 轉譯: \ > - Q. `print('a'b"c"d'e')` > - `'a\'b\"c\"d\'e'` 或 `'a\'b"c"d\'e'` > - 轉譯符 > - `\n` : 換行 > - `\r` : return > - `\t` : tab > - `\b` : 空格 > - `\f` : 換頁 > - `\"` : " > - `\'` : ' > - `\\` : \ > - `\xnn`: 以16進制表示ASCII, 例如`\x40` : @ > - `\unnnn`: 以16進制表示Unicode, 例如`\u0b18` : "ଘ" > - 字符串長度 length ```javascript= a = 'godjj' a.length // 5 ``` > - String 拼接 > `+` 在不同情境有不同作用 ```javascript= // num + num 3+4 // 7 // str + str "haha" + "haha" // "hahahaha" // num + str 123 + "haha" // "123haha" // 先將num轉成str 再拼接 // Boolean + str true + "haha" // "truehaha" // boolean + num true + 123 // 124 = 1+123 false + 123 // 123 = 0+123 ``` ### Boolean > - true = 1/ flase = 0 > - 小寫 ### undefined & null > - null : 空 > - undefined: 沒有賦值 ```javascript= var a = 100 // undefined : 這整句話是沒有賦值的 a // 100 : a 賦值 100 ``` ### object > - 我在python學的那些集合類型,在這都是object ```javascript= a = null typeof a // "object" a = [1,2,3] typeof a // "object" a = (1,2,3) // 3 : 沒有 tuple typeof a // "number" a = {"a":1} typeof a // "object" ``` ### typeof > 查詢變量類型 ```javascript= a = 100 typeof a // "number" a = '100' typeof a // "string" a = true typeof a // "boolean" var a; typeof a // "undefined" a = null typeof a // "object" ``` ## 類型轉換 ### 轉成String > - `var.toString()` 或 `String(var)` > - null(object) 跟 undefined 沒有 toString 方法, 只能用 String() 轉 ```javascript= // 不是真的轉換那個變量, 而是把參數丟進去類或函數所返回的值是str a = 100 // 100 a.toString() // "100" String(a) // "100" a // 100 typeof a // "number" ``` ```python # 用python思考看看 In [1]: def String(i): ...: return str(i) In [3]: a = 100 In [4]: String(a) Out[4]: '100' In [5]: a Out[5]: 100 In [9]: type(a) Out[9]: int # class版本的我還沒想到要怎麼把 a 指向 class num() # 我猜 a 是丟到一個函數判斷是什麼類型 # 然後創那個類型的實例類讓a指向, 調用那個類的函數 toString(), # 而且實例屬性把a的值存起來 # # class num(): # def __init__(self, i): # self.val = i # def toString(self): # return str(self.val) ``` > - 拼接str的方式 ```javascript= 100 + '' // "100" null + '' // "null" undefined + '' // "undefined" ``` ### 轉成數字 > - Number(var) ```javascript= Number('123') // 123 // Number() 轉換時,如果內容有非數字,就直接返回NaN Number('123abc') // NaN // Number() 可以轉換 Boolean Number(true) // 1 Number(false) // 0 // 小數也能轉換 Number('100.1') // 100.1 Number('100.1.1') // NaN ``` ```python # 用正則試試看 In [1]: import re In [23]: a = '100' In [24]: b = 'abc100' In [25]: c = '100abc' In [30]: print(re.match(r'\d.+?\d+$', a)) <re.Match object; span=(0, 3), match='100'> In [31]: print(re.match(r'\d.+?\d+$', b)) None In [32]: print(re.match(r'\d.+?\d+$', c)) None In [41]: a = '100.1' In [42]: b = '100.abc' In [43]: print(re.match(r'\d.+?\d+$', a)) <re.Match object; span=(0, 5), match='100.1'> In [44]: print(re.match(r'\d.+?\d+$', b)) None ``` > - parseInt(var) ```javascript= parseInt('123') // 123 // parseInt() 轉換時,遇到非數字就直接返回 parseInt('123abc') // 123 parseInt('123a4bc') // 123 parseInt('abc') // NaN // parseInt 無法轉換 Boolean parseInt(true) // NaN // parseInt 只轉換整數, 小數點沒有解析 parseInt('123.1') // 123 ``` ```python # 用正則試試看 In [23]: a = '100' In [24]: b = 'abc100' In [25]: c = '100abc' In [27]: print(re.match(r"\d+", a)) <re.Match object; span=(0, 3), match='100'> In [28]: print(re.match(r"\d+", b)) None In [29]: print(re.match(r"\d+", c)) <re.Match object; span=(0, 3), match='100'> ``` > - parseFloat(var) ```javascript= // 除了可以解析小數點外,其他都跟parseInt一樣 parseFloat('100') // 100 parseFloat('100.1') // 100.1 parseFloat('100.1.1') // 100.1 parseFloat('100.abc') // 100 parseFloat('abc') // NaN parseFloat(true) // NaN ``` ```python # 正則試試看 In [20]: a = '100' In [21]: b = '100ba4c' In [22]: c = 'abc100' In [23]: d = '100.1' In [24]: f = '100.1.1' In [26]: g = '100.abc' In [27]: print(re.match(r"\d+.?\d+", a)) <re.Match object; span=(0, 3), match='100'> In [28]: print(re.match(r"\d+.?\d+", b)) <re.Match object; span=(0, 3), match='100'> In [29]: print(re.match(r"\d+.?\d+", c)) None In [30]: print(re.match(r"\d+.?\d+", d)) <re.Match object; span=(0, 5), match='100.1'> In [31]: print(re.match(r"\d+.?\d+", f)) <re.Match object; span=(0, 5), match='100.1'> In [32]: print(re.match(r"\d+.?\d+", g)) <re.Match object; span=(0, 3), match='100'> ``` > - 正負號運算 ```javascript= // 看起來是 Number() 後再前面多一個正負號運算 a = '100' // "100" +a // 100 -a // -100 a // "100" b = '100abc' // "100abc" +b // NaN c = '100.1' // "100.1" +c // 100.1 d = '1.1.1' // "1.1.1" +d // NaN a = true // true +a // 1 -a // -1 // + - 拼接與運算 a = '123' // "123" // + 一邊是str, 另一邊是num時, 會先把num轉str後拼接 a + 0 // "1230" // - 一邊是str,另一邊是num時, 會把str轉num後運算 a - 0 // 123 b = '123abc' // "123abc" b - 0 // NaN: b 無法轉num, 故NaN ``` ### 轉Boolean > - Boolean(var) > - `null`, `undefined`, `''`, `0`, `NaN` 這五種會轉成 flase ```javascript= Boolean(100) // true Boolean('100') // true Boolean(100.1) // true Boolean(null) // false Boolean(undefined) // false Boolean('') // false Boolean(0) // false Boolean(NaN) // false ``` ## 運算子(Operator) ### 算術運算 ```javascript= 1+1 // 2 1-1 // 0 1*1 // 1 1/1 // 1 // % 餘數 3 % 2 // 1 5 % 2 // 1 11 % 3 // 2 ``` ### 一元運算符 > - `1+1`: 二元運算,有兩個值做運算 > - 前置++ ```javascript= a = 1 // 1 ++a // 2 : 描述 +1+a ,返回當前a的值, +1+1=2 a // 2 : 他真的改變變量 ``` > - 後置++ ```javascript= b = 1 // 1 b++ // 1: 描述+b+1,返回當前b的值, 1( b在前面, 還沒有+1 ) b // 2 : 執行完後b的值變 2 ``` ```javascript= var a=1; // undefined // var b = ++a + ++a; a // 3 b // 5 /* * 第一個 ++a的 * 返回: +1+a = +1+1 = 2 * a的值: 2 * 第二個 ++a的 * 返回: +1+a = +1+2 = 3 * a的值: 3 * b = 2+3 = 5 */ // var b = ++a + a++; a // 3 b // 4 /* * ++a * 返回: +1+a = +1+1 = 2 * a的值: 2 * a++ * 返回: 2, * a的值: 3 * b = 2+2 = 4 */ // var b = a++ + ++a; a // 3 b // 4 /* * a++ * 返回: 1 * a的值 2 * ++a * 返回 +1+a = +1+2= 3 * a的值 3 * b = 1+3 = 4 */ // var b = a++ + a++; a // 3 b // 3 /* * 第一個a++ * 返回: 1 * a的值: 2 * 第二個a++ * 返回: 2 * a的值: 3 * b = 1+2 = 3 */ ``` ### 邏輯運算符 ```javascript= // && 與 (並且) a = true b = true a && b // true b = false a && b // false // || 或 a = true b = true a || b // true b = false a || b // true // ! 取反, 一元運算符 a = true b = false !a // false !b // true ``` ### 關係運算符 ```javascript= // < (小於) >(大於) >=(大於等於) <=(小於等於) // ==(等於) !=(不等於) ===(等於) !==(不等於) /* * == 跟 === 都是判斷兩者是否相等, * 差別在於 == 只判斷值是否相等 * === 判斷類型與值是否相等 * !== 與 !=== 亦同 */ a = 10 b = 10 a == b // true a === b // true b = '10' a == b // true a === b // false: b的類型是str, a類型是num, 所以 false ``` ### 賦值運算符 ```javascript= // = a == 100 // Error: a is not defined a = 100 // a 賦值 100 a == 100 // true // += -= *= /= %= a = 100 a = a + 100 // 200 a = 100 a += 100 // 200: 這句話就是 a = a + 100 的簡寫 b -= 100 // b = b - 100 c /= 100 // c = c / 100 d *= 100 // c = c * 100 e %= 100 // e = e % 100 ``` ### 運算符優先級 > 1. `()` > 2. `一元` : `++ -- !` > 3. `算數` : 先 `* / %` 後 `+ -` > 4. `關係` : `> < >= <=` > 5. `相等` : `== === != !==` > 6. `邏輯` : 先 `&&` 後 `||` > 7. `賦值` : `= += -= *= /= %=` ```javascript= // Q. 4 >= 6 || '5566' != '不能亡' && !(12 * 2 == 144) && true /* * !(12*2 == 144) = !0 = 1 * '5566' != '不能亡' = 1 * 4 >= 6 = 0 * 0 || 1 && 1 && 1 * 0 || 1 = 1 */ // Q. var num = 10; // 5 == num / 2 && (2 + 2 * num).toString() === '22' /* * (2+2*num).toString() === '22' = '22' === '22' = 1 * 5 == num/2 = 5 == 5 = 1 * 1 && 1 = 1 */ ``` ### 冷知識 ```javascript= 0>null // false 0<null // false 0=null // false 0>=null // true 0<=null // true // ? ``` > - 他運算 >= 跟 <= 的方法是看有沒有 < 或 > > 如果 true 或 undefined 就返回 false, 沒有就返回 true > - `0 >= null` -> `0 < null // false`, > 0 不小於 null, 所以 0>=null > - https://www.ecma-international.org/ecma-262/5.1/#sec-11.8.4 > - Let r be the result of performing abstract relational comparison lval < rval. > - If r is true or undefined, return false. Otherwise, return true. ## 表達式與語句 ### 表達式( Expression ) > - 表達式可以產生一個值, 如運算, 調用函數等 > - 例如 `5+5` 得到10; `String(5)` 得到 '5' ### 語句 > - code 的每句話都是語句, 每一句語句都用 `;` 分開 ## 分支結構 ### IF ```javascript= /* if ( 條件1 ) { 執行1 } else if ( 條件2 ) { 執行2 } else if ( 條件3 ){ 執行3 } else { 執行4 } */ var num1 = 10; var num2 = 5; // Q. 判斷兩個值得大小 if (num1 > num2) { 'MaxNum: ' + num1 } else if (num1 < num2){ 'MaxNum: ' + num2 }; // "MaxNum: 10" // Q. 判斷值是奇數還是偶數 if (num1%2 === 0) { 'num1 is even' } else { 'num1 is odd' }; // "num1 is even" // Q. 轉換成績 // >=90: A; // 80-89: B; // 70-79: C; // 60-69: D; // <60: F; var score = 80; /* 錯誤寫法 if (score>=90) { score = 'A' } else if (90>score>=80) { // 數學是這樣寫, 但程序不行, 程序要拆開 score = 'B' } else if (80>score>=70) { score = 'C' } else if (70>score>=60) { score = 'D' } else if (60>score) { score = 'E' }; */ /* 精確的寫法 if (score>=90) { score = 'A' } else if (score>=80 && score<90) { score = 'B' } else if (score>=70 && score<80) { score = 'C' } else if (score>=60 && score<70) { score = 'D' } else { score = 'E' } */ /* 由於分數大於等於90分就會執行 score = 'A' 而不會繼續往下判斷 * 所以判斷過的語句就都可以省略掉了 */ if (score>=90) { // 判斷完這句, 如果沒有執行, 表示值小於 90 而往下繼續判斷 score = 'A' } else if (score>=80) { // 判斷之前, 值已是小於 90 了, 所以不用重複寫 score = 'B' } else if (score>=70) { // 判斷之前, 值已是小於 80 了, 所以不用重複寫 score = 'C' } else if (score>=60) { // 判斷之前, 值已是小於 70 了, 所以不用重複寫 score = 'D' } else { score = 'E' } // Q. 判斷年紀是否大於18 var age = 19; if (age>18) { 'age:' + age + ' > 18' } else { 'age:' + age + ' < 18' } // Q. 判斷是否為閏年(可以被4整除, 但不是被100整除, 或是可以被400整除) if (year%4 === 0 && year%100 !== 0 || year%400 === 0) { '閏年' } else { '不是閏年' } ``` ### 三元表達式 > - `if (){}else{};` 的縮寫 ```javascript= // 表達式1 ? 表達式2 : 表達式3; /* * 如果表達式1成立, 就執行表達式2, 否則執行表達式3 * 相當於: * if (表達式1) { * 表達式2 * } else { * 表達式3 * }; */ // 例1 /* if (num1 > num2) { '已成年' } else if (num1 < num2){ '未成年' }; */ // num1 > num2 ? '已成年' : '未成年'; var MaxNum = num1 > num2 ? num1 : num2; // 例2 /* if (age>18) { 'age:' + age + ' > 18' } else { 'age:' + age + ' < 18' } */ // age>18 ? 'age:'+age+'>18' : 'age:'+age+'<18' var Tommy = TommyAge > 18 ? '已成年': '未成年'; ``` ### Switch > - 判斷 Expression( 表達式 ) 的值是否與 Constant( 常量 ) 相等 > - 亦即 Switch 只能做相等判斷 > - Switch 是用 `===` 來判斷的 > - 執行語句最後記得加 `break;` 跳出, 否則他會一直執行到 `break;` 或 結束 ```javascript= // switch (Expression) { // case Constant1: // 語句1; // break; // case Constant2: // 語句2; // break; // case ...: // ...; // break; // default: // 語句; // break; // } var day = 2; /* * 明明有設 '2' , 結果卻是 default ? * 因為 switch是用 === 判斷, 所以前面兩個都是 false * switch (day) { case '1': console.log('星期一'); break; case '2': console.log('星期二'); break; default: console.log('我只有設星期一跟星期二, 我就是傲嬌'); break; } // '我只有設星期一跟星期二, 我就是傲嬌' */ switch (day) { case 1: console.log('星期一'); break; case 2: console.log('星期二'); break; default: console.log('我只有設星期一跟星期二, 我就是傲嬌'); break; } // '星期二' /* 記得每個判斷後都要跳出 break; * 否則他會一直輸出到 break; 或 最後一行為止 * var day = 1; switch (day) { case 1: console.log('星期一'); case 2: console.log('星期二'); case 3: console.log('星期三'); default: console.log('我只有設星期一跟星期二, 我就是傲嬌'); } // 星期一 // 星期二 // 星期三 // 我只有設星期一跟星期二, 我就是傲嬌 */ // 轉換分數 var score = 90 /* 吃飽太閒法: switch (score) { case 100: case 99: case 98: // ... case 90: score = 'A'; } // "A" score // "A" */ score = parseInt(score/10); switch (score) { case 10: case 9: score = 'A'; break case 8: score = 'B'; break case 7: score = 'C'; break case 6: score = 'D'; break default: score = 'E'; break } // "A" ``` ### Boolean 隱式轉換 ```javascript= // 顯示轉換 /* var a = 100; * Boolean(a) // true */ // 隱式轉換 // if 判斷的時候會轉Boolean後判斷true, false /* var a = 100; if (a) { console.log('true') } else { console.log('false') } // true */ var a; // NaN, 0, '', undefined, null if (a) { console.log('true') } else { console.log('false') } // false // ! 取反運算 var a = '123' // undefined a // "123" var a = !'123' // undefined a // false var a = !!'123' // undefined a // true ``` ## 循環結構 ### while ```javascript= /* while () { * } */ /* Python In [4]: i = 1 In [5]: while i <= 10: ...: print(i) ...: i+=1 */ var i = 1; while (i<=10) { console.log(i); // i = i + 1; // i+=1; i++; } /* Python In [21]: i = 1 In [22]: j = 0 In [24]: while i <= 10: ...: j = j + i ...: i += 1 */ var i = 1; var j = 0; while (i <= 10) { j+=i; i+=1; } console.log(i,j); /* Python In [41]: i = 1 In [42]: while i <= 100: ...: if i%7 == 0: ...: print(i) ...: i+=1 */ var i = 1; while (i<=100) { if (i%7 === 0) { console.log(i) } i+=1; } /* python In [67]: i = 0 In [68]: j = 0 In [69]: while i <= 100: ...: if i%2 == 0: ...: j+=i ...: i+=1 */ var i = 0 var j = 0 while (i<=100) { if (i%2 === 0) { j+=i } i+=1 } console.log(i,j) // 101, 2550 ``` ### do...while... > - 特色: 會先執行一次循環體後再判斷 ```javascript= /* 語法 do { // 循環體 } while (條件) * 先執行一次do, * 如果while條件為 true, * 繼續執行do */ var i = 0; var j = 0; /* while (i<=100) { j+=i i+=1 } console.log(i,j); // 101, 5050 */ do { j+=i i+=1 } while (i<=100) console.log(i,j); // 101, 5050 // 恐怖情人 /* while 的寫法 var msg = prompt('你愛我嗎?', '請填入Y/N') while (msg !== 'Y') { msg = prompt('你愛我嗎?', '請填入Y/N') } */ do { // 用 do 先問一次, 比較簡潔一點點 var msg = prompt('你愛我嗎', '請填入Y/N'); } while (msg !== 'Y') ``` > - prompt('', '') > - `prompt('hihi', 'wiwi')` > <img src="https://i.imgur.com/H11Cu7d.png" style="width: 300px;"/> > - 第二個參數類似於 `<input type='text' value:'wiwi'/>` 的 value ```javascript= prompt('hihi', 'wiwi'); // "123" : 返回一個str ``` ### for > - 跟Python很不一樣 ```javascript= /* for (初始化表達式(1); 判斷表達式(2); 自增表達式(3)) { // 循環體(4) } * (1)>(2)>(4)>(3)>(2)>(4)>(3)>... * 注意(1);(2);(3) 是分號隔開,不是逗號! */ /* while var i = 0; // (1) while (i <= 100) { // (2) console.log(i); // (4) i+=1; // (3) } */ for (var i=0; i<=100; i+=1){ console.log(i); } /* for的表達式是可以省略的 var i = 0; for (;i<=100;) { // 1. ; 不能省 2. 判斷條件省了就會一直true而造成死循環 console.log(i) i+=1 } */ // 1-100 sum, avg var sum = 0; var avg; for (var i=1; i<=100; i+=1) { sum+=i } console.log(i, sum) // 101, 5050 avg = sum/(i-1) console.log(avg) // 0-100 偶數和 var sum = 0; // 記得要讓sum附值, 否則NaN沒辦法運算(註) for (var i=1; i<=100; i+=1) { if (i%2 === 0) { sum+=i; } } console.log(i, sum) /* 註 a = NaN // NaN a + 1 // NaN */ // 0-100 奇數和 與 偶數和 var oddSum = 0 var evenSum = 0 for (var i=0; i<=100; i+=1) { if (var i%2 === 0) { evenSum+=i } else { oddSum+=i } } console.log('奇數和: ' + oddSum) console.log('偶數和: ' + evenSum) // ---------------------------- // // 輸出10*10的星星排列正方形 /* Python 解一 In [38]: a = '' In [39]: for i in range(10): # 10行 ...: for j in range(10): # 一行10個 ...: a+="* " ...: a+="\n" In [40]: print(a) */ var a = ''; for (var i=0; i<10; i+=1) { // 10行 for (var j=0; j<10; j+=1) { // 10列 a+='* '; } a+='\n' } console.log(a) /* python 解二 In [64]: for i in range(10): ...: print("* "*10) */ /* js 的 str好像不能乘 a = '*' // "*" a*10 // NaN */ // ---------------------------- // // 輸出 10*10 正三角 /* python 解一 In [83]: a = '' In [84]: for i in range(10): # 十行 ...: for j in range(i): # 第一行一個, 第二行兩個 ...: a+='* ' ...: a+='\n' In [85]: print(a) */ /* JS 解 1-1 */ var a = ''; for (var i=1; i<=10; i+=1) { for (var j=i; j>0; j-=1) { // 第一行一個 a+="* "; } a+='\n' } console.log(a); /* JS 解 1-2 */ var a = ''; for (var i=9; i>=0; i-=1) { for (var j=i; j<10; j+=1) { // 第一行一個 a+="* "; } a+='\n' } console.log(a); /* python 解二 In [82]: for i in range(10): ...: print('*'*i) */ // --輸出10*10 的倒三角形-------------------------- // /* python 解一 In [94]: a = '' In [96]: for i in range(10,0,-1): ...: for j in range(i): ...: a+='* ' ...: a+='\n' In [97]: print(a) */ /* jS解 1-1 */ var a = '' for (var i=10; i>0; i-=1) { for (var j=i; j>0; j-=1) { // 第一行十個 a+='* ' } a+='\n' } console.log(a) /* JS 解 1-2 */ var a = '' for (var i=0; i<10; i+=1) { for (var j=i; j<10; j+=1) { // 第一行十個 a+='* ' } a+='\n' } console.log(a) /* python 解二 In [62]: for i in range(10,0,-1): ...: print("* "*i) */ // --九九乘法表--------------------- // /* Python In [108]: for i in range(1,10): ...: for j in range(1,10): ...: print('%d*%d=%-2d ' % (i,j,i*j), end='') ...: print('\n') # %2d: 數字寬度為2, 如果只有一位數, 向右對齊, 左邊補空格 # %-2d: 數字寬度為2, 如果只有一位數, 向左對齊, 右邊補空格 # %02d: 數字寬度為2, 如果只有一位數, 向右對齊, 左邊補0 (%.2d也一樣) */ var a = '' for (var i=1; i<10; i+=1) { for (j=1; j<10; j+=1) { // a+=(i+'*'+j+'='+i*j+' '); : 有些結果個位數,有些十位數, // 位置會跑掉, 所以改'\t' a+=(i+'*'+j+'='+i*j+'\t'); } a+=('\n'); } console.log(a) // 三角形九九乘法表 var a = '' for (var i=1; i<10; i+=1) { for (var j=i; j<10; j+=1) { a += (i+'*'+j+'='+i*j+'\t') } a+='\n' } console.log(a) // Q. 本金10000元存入銀行,年利率是千分之三, // 每過1年,將本金和利息相加作為新的本金。計算5年後,獲得的本金是多少? /* python In [30]: money = 10000 In [31]: for i in range(1,6): ...: money = money * 1.003 In [32]: money Out[32]: 10150.902704052423 */ var money = 10000; for (i=1; i<=5; i++) { money *= 1.003; } console.log(money); // 10150.902704052423 // Q. 有個人想知道,一年之內一對兔子能繁殖多少對?於是就築了一道圍牆把一對兔子關在裡面。 // 已知一對兔子每個月可以生一對小兔子,而一對兔子從出生後第3個月起每月生一對小兔子。 // 假如一年內沒有發生死亡現象,那麼,一對兔子一年內(12個月)能繁殖成多少對? // (兔子的規律為數列,1,1,2,3,5,8,13,21) /* python In [78]: firstMonth = 1 In [79]: secondMonth = 1 In [80]: Month = 0 In [81]: for i in range(3,13): ...: Month = firstMonth + secondMonth ...: firstMonth = secondMonth ...: secondMonth = Month ...: print(Month) 2 3 5 8 13 21 34 55 89 144 */ var firstMonth = 1; var secondMonth = 1; var Month = 0 for (var i=3; i<=12; i++) { Month = firstMonth + secondMonth; firstMonth = secondMonth; secondMonth = Month; // console.log(firstMonth, secondMonth,Month); } console.log(Month); // 144 ``` ### break & continue > - break : 跳出整個循環, 終止循環 > - continue : 跳出這次循環,繼續下一次循環 ```javascript= // Q. 求 50 - 200 首個能被 7 整除的數 /* Python In [66]: for i in range(50, 201): ...: if i % 7 ==0: ...: print(i) ...: break 56 */ for (var i=50; i<=200; i++) { if (i % 7 === 0) { console.log(i) break } } // 56 // Q. 求 1-100 累加, 但跳過個位數為3的值 /* Python In [71]: Sum = 0 In [75]: for i in range(0,101): ...: if i % 10 != 3: ...: Sum+=i In [76]: Sum Out[76]: 4570 */ // 解一 var sum = 0 for (var i=1; i<=100; i++) { if (i%10 !== 3) { sum += i } } // 4570 // 解二(continue) var sum = 0; for (var i = 1; i<=100; i++) { if (i%10 === 3) { continue // 餘數為3時, 跳出當次循環 } sum += i } // 4570 // Q. 1-100 不能被7整除的和(continue) var sum = 0 for (var i = 1; i <= 100; i++) { if (i%7 === 0 ) { continue; } sum+=i; } ``` ## 調適(Debug) ### 語法錯誤: 打錯 > - `for (i=100, 1<1000, 1++) {}` > ![](https://i.imgur.com/Sg2Umzx.png) > ![](https://i.imgur.com/7FcfZAJ.png) > ### 邏輯錯誤: ```javascript= // Q. 算1-100的和 /* var sum = 1; for (var i=1; i<100; i++) { sum+=1; } console.log(sum); // 100 : 跟預期的結果有很大的出入 */ ``` > #### 調適方法 > - alert() > ![](https://i.imgur.com/sPic4QD.png) > - 一個一個跳結果出來, 缺點就是一定要跳完,不然就是關掉, 不是很好用 ```javascript= var sum = 1; for (var i=1; i<100; i++) { sum+=1; alert(sum); } console.log(sum); ``` > - console.log() > - 類似 python 的 print > ![](https://i.imgur.com/CTYhjZz.png) ```javascript var sum = 1; for (var i=1; i<100; i++) { sum+=1; console.log(sum); } console.log(sum); ``` > - 斷點調適 > - 類似 Python 的 PDB > - 什麼都沒做時 > ![](https://i.imgur.com/tJ31pCF.png) > - 點一下行數會產生標記,此時code會執行到標記的上一行止 > ![](https://i.imgur.com/OTkwKlh.png) > ![](https://i.imgur.com/7N2IGtq.png) > - 點擊下的圖標,標記會跳到下一行 > ![](https://i.imgur.com/Gieu7mK.png) > ![](https://i.imgur.com/Dio50xY.png) > ![](https://i.imgur.com/TTm0XnM.png) ## 陣列(Array) `[, , ,...]` ```javascript= // 有序列表 // 可裝不同類型 var arr = [1, 1.1, 'haha', true, undefined, null] // 提取: 陣列名[下標/索引] // 下標第一個為0, 最後一個為陣列長度-1 arr[0] // 1 arr[1] // 1.1 arr[4] // undefined arr[5] // null arr[6] // undefined // 陣列長度: `陣列名.length` console.log(arr.length) // 6 // 提取最後一個元素: 陣列名[陣列長度-1] console.log[arr[arr.length-1]] // null // 改 // 陣列名[下標/索引] = 附值, 下標下 長度-1內 的值 var arr = [1,2,3,4] arr[0] // 1 arr[0] = 9 // 11 console.log(arr); // (4) [9, 2, 3, 4] // 增 // 陣列名[下標/索引] = 附值, 下標下 超出長度-1 的值 // 沒有超出的部分會自動補 undefined var arr = [1,2,3,4] arr[6] = 0 console.log(arr); // (7) [1, 2, 3, 4, empty × 2, 0] arr[5] = undefined // 遍歷陣列 var arr = [1,2,3,4] // undefined for (i=0; i<arr.length; i++) { console.log(arr[i]) } // 倒敘遍歷 var arr = [1,2,3,4] for (i=arr.length-1; i>=0; i--) { console.log(arr[i]); } // 應用 var test = []; for (i=0; i<5; i++) { test[i] = i; } console.log(test); // (5) [0, 1, 2, 3, 4] // 清空陣列 var arr = [1,2,3,4] arr.length = 0 console.log(arr); // [] // Q. 求一組數中所有數的和與平均值 var arr = [1,2,3,4,]; var sum = 0; var avg; for (var i=0; i<4; i++) { sum += arr[i]; } avg = sum/arr.length; console.log('和: ' + sum); console.log('平均: ' + avg); // Q. 求一組數中最大值與最小值, 以及所在位置 var arr = [11,2,44,14,32]; var max = arr[0]; var min = arr[0]; var maxIndex = 0; // 避免第一個值就是最大值而造成maxIndex到循環結束都沒有賦值 var minIndex = 0; for (var i=1; i<arr.length; i++) { if (max < arr[i]) { max = arr[i] maxIndex = i } if (min > arr[i]) { min = arr[i] minIndex = i } } console.log('最大值: ' + max + '; 位置在: ' + maxIndex); console.log('最小值: ' + min + '; 位置在: ' + minIndex); // Q. 將字符串陣列用 | 隔開,形成一串字符串 // 解一 var strs= ['1', '2', '3', '4']; var str = ''; var separator = ' | '; for (i=0; i<strs.length; i++) { if (i<strs.length-1) { // str = str + strs[i] + ' | ' // 避免在表達式中寫一個固定的值 str = str + strs[i] + separator; } else { str = str + strs[i]; } } // 解二 var strs= ['1', '2', '3', '4']; var str = strs[0]; var separator = ' | '; for (i=1; i<strs.length; i++) { // str = str + separator + strs[i]; str += separator + strs[i]; } // Q. 將陣列第0項移除, 將陣列中不為0的值存入新陣列 var nums = [2,4,66,0,21,0,13]; var newNum = []; for (i=1; i<nums.length; i++) { if (nums[i] !== 0) { // newNum[i]=nums[i] // (7) [empty, 4, 66, empty, 21, empty, 13] // 問題: 形成一個不連續的陣列 newNum[newNum.length] = nums[i]; // (4) [4, 66, 21, 13] // 註 } } console.log(newNum); // 註: var test = []; console.log(test.length); // 0 test[test.length] = 3; console.log(test.length); // 1 test[test.length] = 88; console.log(test.length); // 2 console.log(test); // (2) [3, 88] // Q. 反轉陣列 var arr = [1,2,3,4]; // > [4,3,2,1] var newArr = []; for (var i=arr.length-1; i>=0; i--) { newArr[newArr.length] = arr[i]; } arr = newArr; console.log(arr); // Q. 冒泡排序 /* 每次兩個位置比較, 跑一圈就會決定最後一個的值, * 確定之後就不用跑了, 所以每圈-1次比較次數 */ /* [0] [1] [2] [3] n = length = 4 第一次 [0]<>[1] [1]<>[2] [2]<>[3] > 確定[3] n-1 > n-j 第二次 [0]<>[1] [1]<>[2] > 確定[2] n-2 > n-j 第三次 [0]<>[1] > 確定[0], [1] n-3 > n-j n-1圈 */ var alist = [54,26,93,17,77,31,44,55,20]; var count = 0; // 紀錄大O // 控制趟數, 每趟找到一個最大值 for (j=1; j<alist.length; j++) { // 假設n=4, j=1~3(3圈)<4 count++; // 記錄一下大O console.log('第'+ j + '圈'); var isSort = true; // 假設序列已經排好了 // 控制比較次數,判斷大小,大的往後移 for (var i = 0; i<alist.length-j; i++) { // j=1, i=0~2<(4-1); > 三次 // j=2, i=0~1<(4-2); > 兩次 // j=3, i=0~0<(4-3); > 一次 count++; // 算一下大O // 如果前面比後面大 if (alist[i] > alist[i+1]) { // 交換 var temp = alist[i]; alist[i] = alist[i+1]; alist[i+1] = temp; // 有交換表示還沒排序完成, 改成false; isSort = false; } console.log(alist); // 監控作用 } console.log(isSort); // 內圈整趟比較完後, 如果都沒有進入if交換, 表示排序完成而不用在跑下一圈了 if (isSort) { break } } console.log(count) // 看總共跑多少圈循環 /* * [17, 20, 26, 31, 44, 54, 55, 77, 93] * 28 */ ```