# [JS101] 用 JavaScript 一步步打造程式基礎(筆記) ###### tags:`Lidemy學院` `[JS101] 用 JavaScript 一步步打造程式基礎` # Node.js 環境建置 ## 該如何執行 JavaScript? 從JavaScript打照程式基礎,JavaScript是一個程式語言,在來就是執行環境,最簡單的方式,就是打開瀏覽器,按右鍵在開發者工具裡的console輸入JavaScript的程式。 還有Node.js也能執行JavaScript的程式,**Node.js是一個運行環境,能讓JavaScript跑在瀏覽器外**。 ## Windows [nodejs下載](https://nodejs.org/zh-tw/),請到官網下載node.js。 [git下載](https://git-scm.com/),請到官網下載git。 使用git-bash來執行指令。 ``` //開啟git-bash,輸入 node -v //會顯示,node的版本號,代表安裝成功 ``` [JavaScript 教學](https://www.fooish.com/javascript/) ## 在瀏覽器裡寫 JavaScript 打開瀏覽器,按右鍵在開發者工具裡的console輸入JavaScript的程式。 ___ # 抱歉這是傳統:你的第一支小程式 ```javascript= //開啟git-bash,輸入node,進入JavaScript的程式執行環境 //印出hello world console.log('hello world') ``` ___ # 連小學生都會的基本運算 ## 算數運算:加減乘除以及取餘數 ```javascript= //+ - * / % () 的用法練習 console.log(1+1) //2 console.log(1-1) //0 console.log(1*1) //1 console.log(1/1) //1 console.log(1%1) //0 console.log((1+1)*1) //2 ``` ## 邏輯運算:and、or 與 not or : 有一邊為true,就為true and : 有一邊為false,就為false not : 輸入為輸入的相反 ```javascript= // ||(or) &&(and) !(not) true || true //true false || true //true false || false //false true && true //true false && true //false false && false //false !true //false !false //true ``` ## 邏輯運算的小撇步:|| 與 && 的短路性質 在JavaScript中,**數字跟字串,也能進行|| 與 &&** **短路性質 :** * || : 左邊輸入true,輸出必為true,左邊輸入false,輸出為右邊決定。 * && : 左邊輸入false,輸出必為false,左邊輸入true,輸出為右邊決定。 **數字 :**  * 0 : false * 其他正數 : true ```javascript= //舉例 3 || 10 //3 false || 10 //10 0 || 10 //10 3 && 10 //10 false && 10 //false 0 && 10 //0 ``` ___ # 我們不一樣:位元運算 ## 左左右右:位移運算子 在觀看此單元之前需要有二進位的基礎,如果不知道什麼是二進位的話,可以參考[CS101] 初心者的計概與 coding 火球術的 3-1:二進位是什麼--電腦中的資料儲存與表示方法。 另外補充影片一個有誤的地方,往右移如果不能整除的話會是無條件捨去,所以 5 >> 1 會是 2。 這跟2進制有關 : 0100<sub>(2)</sub> = 4<sub>(10)</sub> <<(左移) 1000<sub>(2)</sub> = 8<sub>(10)</sub> 相當於乘2 1000<sub>(2)</sub> = 8<sub>(10)</sub> >>(右移) 0100<sub>(2)</sub> = 4<sub>(10)</sub> 相當於除2 ```javascript= >>(右移) : 相當於除2 <<(左移) : 相當於乘2 8 >> 1 //右移1位,8/2=4 8 >> 2 //右移2位,8/2/2=2 2 << 1 //左移1位,2*2=4 2 << 2 //右移2位,2*2*2=8 ``` ## 位元運算的 and、or、xor 與 not &(and) : 1010<sub>(2)</sub> & 1111<sub>(2)</sub> = 1010<sub>(2)</sub> |(or) : 1010<sub>(2)</sub> | 1111<sub>(2)</sub> = 1111<sub>(2)</sub> ~(not) : ~1111<sub>(2)</sub> = 0000<sub>(2)</sub> ^(xor) : 1010<sub>(2)</sub> ^ 1111<sub>(2)</sub> = 0101<sub>(2)</sub> 舉例 : 某數 & 1 => 0 ,某數的最後1個數為0,並為偶數 某數 & 1 => 1 ,某數的最後1個數為1,並為基數 ```javascript= 10 & 1 //0,偶數 11 & 1 //1,基數 //判斷基偶數,也可以 10 % 2 //0,偶數 11 % 2 //1,基數 ``` ___ # 放東西的箱子:變數(Variable) ## 大聲告白:變數宣告與 undefined 變數就是一個裝東西的箱子,那以後就能用箱子的名稱來指箱子內的東西,是一個賦值的概念,將右值賦於左邊。 null:這地方會有一個值,但這個值目前還沒準備好的意思,所以先填入 null undefined:有宣告這變數,但沒值 NaN:要轉型成數字時傳入參數非數字的時候 ```javascript= var box = 123 console.log(box) //123 var box1 console.log(box1) //undefined,有宣告這變數,但沒值 console.log(box2) //not defined,沒宣告這個變數, var userId //駝峰式命名法 var User_Id //少用縮寫,多使用完整單字,單字間用下劃線『 _ 』區隔 ``` 變數的命名方式: [命名規則 ](https://zh.wikipedia.org/wiki/%E5%91%BD%E5%90%8D%E8%A7%84%E5%88%99_(%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1)) [學習有意義的命名](https://medium.com/mr-efacani-teatime/%E6%92%B0%E5%AF%AB%E7%A8%8B%E5%BC%8F%E7%9A%84%E7%AC%AC%E4%B8%80%E6%AD%A5-%E5%AD%B8%E7%BF%92%E6%9C%89%E6%84%8F%E7%BE%A9%E7%9A%84%E5%91%BD%E5%90%8D-62252ea86587) ## 安安,可以 ++ 嗎 ```javascript= var a = 0 a = a + 5 console.log(a) //5 a += 5 console.log(a) //10 a = a + 1 console.log(a) //11 a++ console.log(a) //12 ++a console.log(a) //13 ``` ```javascript= //a++跟++a的區別 var a = 0 a = a + 1 console.log(a) //1 a++ //會先將a值賦於左邊a在計算 ++a //會先執行a = a + 1在將值給左邊 ``` [i++ 與 ++i可以怎麼理解?](https://ithelp.ithome.com.tw/articles/10192800) ## 一樣米養百樣人:變數的各種型態 typeof * typeof 運算字用來判斷一個運算元 (operand) 是什麼資料型態。 ```javascript= typeof 30 //number ``` 第一種是基本資料型態 (primitive data types),基本資料型態包含了: * boolean : 只包含兩種值 true / false * number : 值類型的值,像是 42 / 3.14159 / 0 * string : 像是 'hello world' / 汽車 ```javascript= console.log('typeof true',typeof true) //boolean console.log('typeof 30',typeof 30) //number console.log('typeof 0.5',typeof 0.5) //number console.log('typeof hello',typeof 'hello') //string console.log('typeof "30"',typeof '30') //string ``` 第二種是複合資料型態 (composite data types),包含了: * object : 基本上,基本資料型態以外的都是物件型態 * undefined : undefined 也是一個特殊值 (keyword),表示值還沒有定義或還未指定 * function ```javascript= console.log('typeof [1]',typeof [1]) //object console.log('typeof {a: 1}',typeof {a: 1}) //object console.log('typeof null',typeof null) //object console.log('typeof undefined',typeof undefined) //undefined console.log('typeof funcion(){}',typeof funcion(){}) //funcion ``` ## 物以類聚:陣列(Array) 陣列 : 陣列用來儲存多個資料,陣列中的資料數量,就是這個陣列的長度 (length) ```javascript= //陣列的宣告 var score = [] //score是一個空陣列 var score = [1,2,3,4,5] //陣列也能先放初始值 var score[0] = 1 //陣列 key = 0,value = 1 console.log(score.length) ``` [JavaScript Array (陣列)](https://www.fooish.com/javascript/array/) ## 最直覺的變數型態:物件(Object) ```javascript= //宣告物件 //方法1 var myObj = new Object(); //方法2 var myObj = {}; //宣告物件並加初始值 var obj = { property1: value1, property2: value2, ..., propertyN: valueN } //.可以來存取物件的屬性。 obj.property1 //[]可以來存取物件的屬性,用 [] 特別的地方在於,中括號裡面可以是一個變數 obj[property1] //舉例 var students = { name: 'peter', address: 'Taipei', phone: '0912345678', father:{ name: 'nick', phone: '0988888888' }, scores:[100,90], age:18 } console.log(students.name); //peter console.log(students['name']); //peter console.log(students.father.name); //nick console.log(students['father']['name']); //nick ``` **this 是物件方法中可以使用的關鍵字,this 是一個物件參考,當物件在執行時,可以使用 this 來代表 "自己"。** ## 沒那麼簡單:變數的運算 需要注意的點:型態 ```javascript= //需轉換型態 var a = '20' var b = 10 console.log(a+b); //2010 console.log(Number(a)+b); //30 console.log(parseInt(a, 10)+b); //30 //parseInt() 函式能將輸入的字串轉成整數。 //parseInt(string, radix); //string,待轉成數字的字串。 //radix,進位系統的數字。通常都是10進位 ``` 需要注意的點:浮點數誤差 ```javascript= var a = 0.1 + 0.2 console.log(a == 0.3) //false console.log(a) //0.300000000004 ``` 補充 : [javascript浮點數的陷阱](https://tso1158687.github.io/blog/2018/12/17/javascript-float-trap/) ## 萬年經典題:== 與 === == 與 ===差別在於型態 == : 不會比較型態 === : 會比較型態 ```javascript= //常用在判斷數字跟字串的內容是否相等 console.log(1 == '1'); //true console.log(1 === '1'); //false ``` ## 從 Object 的等號真正的理解變數 ```javascript= //陣列跟物件裡面,可以想像是存記憶體位址 console.log([] === []); //false console.log([1] === [1]); //false console.log({} === {}); //false console.log({a: 1} === {a: 1}); //false ``` ```javascript= var obj = { a: 1 } console.log(obj === {a: 1}); //false,記憶體位址,指向不同 var obj2 = obj //想像存記憶體位址,指向同一個 console.log(obj2 === obj); //true,存記憶體位址,指向相同 obj2.a = 2 console.log(obj2 === obj); //true,obj2.a一樣改到obj.a的值,因為指向同一個 obj2 = {b: 1} console.log(obj2 === obj); //false,指向不同記憶體位址 ``` [JavaScript Object (物件)](https://www.fooish.com/javascript/object.html) ___ # 我們只能往不同地方走去:判斷式 ## 如果我說,愛我沒有如果:if/else statement ```javascript= //判斷式 if(true){ console.log('if條件為true,輸出') } //舉例 var number = 11 if(number % 2 ===0){ console.log('偶數') }else{ console.log('基數') } ``` ## 不只一條活路:if/else if statement ```javascript= /* age >=65 ,old man 65 > agd >=20 ,young age <20 ,children */ var age = 40 if(age >= 65){ console.log('old man'); }else if(65 > age && age >= 20){ console.log('young'); }else if(age < 20){ console.log('children'); } ``` ## 太多太多的選擇:switch case ```javascript= var season = '春' switch(season){ case '春': console.log('春天'); break; case '夏': console.log('夏天'); break; case '秋': console.log('秋天'); break; case '冬': console.log('冬天'); break; default: console.log('輸入不是季節'); } ``` ## 一、二、三:三元運算子(Ternary) ```javascript= //conditon ? A : B var socre = 60 var message = socre >= 60 ? 'pass' : 'fail' console.log(message); //pass ``` ## 練習一:判斷是否及格 請你自己寫出一段程式碼,是判斷一個叫做 score 的變數是否及格(超過或剛好 60 分),如果及格的話就輸出 pass,否則輸出 fail。 進階練習: 除了判斷是否及格以外,也請你對滿分做出特別判斷,如果是 100 分的話就輸出 you are no1! ```javascript= var socre = 60 if(socre == 100){ console.log('you are No.1'); }else if(socre >= 60){ console.log('pass'); }else if(socre < 60){ console.log('fail'); } ``` ## 練習二:BMI 計算 BMI 值的計算公式為:體重 / 身高^2。 假設體重是 70,身高是 180(1.8m),BMI 就是 70/(1.8*1.8) = 21。 現在請你寫出一個簡單的 BMI 計算器,用兩個變數代表體重跟身高,算出 BMI 之後判斷 BMI 是落在哪個範圍內並輸出相對應的字串。 體重過輕:BMI < 18.5 正常範圍:18.5 <= BMI < 24 過重:24 <= BMI < 27 輕度肥胖:27 <= BMI < 30 中度肥胖:30 <= BMI < 35 重度肥胖:35 <= BMI ```javascript= var weight = 70 //體重(kg) var height = 1.8 //身高(m) var BMI = weight/(height*height) console.log(BMI) if(BMI >= 35){ console.log('重度肥胖') }else if(35 > BMI && BMI>=30){ console.log('中度肥胖') }else if(30 > BMI && BMI>=27){ console.log('輕度肥胖') }else if(27 > BMI && BMI>=24){ console.log('過重') }else if(24 > BMI && BMI>=18.5){ console.log('正常範圍') }else if(18.5 > BMI){ console.log('體重過輕') } ``` ___ # 跟我一起跑操場:迴圈 ## 迴圈的前世:label 與 goto 在JavaScript沒有此指令,在其他程式語言有。 ```javascript= var i = 1 //初始值 label: console.log(i) i++ //i+1 if(i<=10){ //條件成立,跳回lable,條件不成立,跳出 goto lable } console.log('i=',i) ``` ## 先做再說:do...while... ```javascript= var i = 1 do{ console.log(i) i++ if(i%2 === 1 ){ continue } console.log('continue') }while(i<=10) ``` ## 試圖擺脫無盡的輪迴:while 迴圈 ```javascript= var i = 1 //初始值 while(i<=10){ //終止條件 console.log(i) //迴圈內要做的事 i++ //i每圈要做的事 } ``` ## 不知道該怎麼下標題的迴圈:for loop ```javascript= for(初始值;終止條件;i每圈要做的事){ } for(i=1;i<=10;i++){ console.log(i); } var socre = [50,60,70,80,90,100] var sum = 0 for(i=0; i<socre.length; i++){ sum+=socre[i] } console.log(sum); ``` ___ # 最後一塊拼圖:函式(Function) ## 最基本的函式結構 ```javascript= /* generateArray(3) => [1,2,3] generateArray(5) => [1,2,3,4,5] */ function generateArray(n){ var result = [] for(i=1; i<=n; i++){ result.push(i) } return result } console.log(generateArray(3)) ``` ```javascript= /* 輸出50內的基數 */ function logEven(number){ if(number%2){ console.log(number) } } function print1to50(){ for(i=1; i<=50; i++){ logEven(i) } } print1to50() ``` ## 宣告函式的不同種方式 ```javascript= //一般宣告function的方式 function hello(){ console.log('hello') } hello() //輸出 => hello //function也是一種資料型態,可以宣告變數去= var hello = function(){ console.log('hello') } console.log(hello) //輸出 => [Function: hello] console.log(hello()) //輸出 => hello hello() //輸出 => hello ``` ```javascript= //函數的參數可以傳函式去使用 function transform(arr, transformFunction){ var result = [] for(var i=0;i<arr.length; i++){ result.push(transformFunction(arr[i])) } return result } //第一種 var triple = function (x){ return x*3 } //第二種 function triple (x){ return x*3 } console.log( transform([1,2,3],triple) ) ``` ```javascript= //匿名函式(anonymous function) : 就是沒有名稱的函示 //範例transform([1,2,3], transformFunction()) => [3,6,9] function transform(arr, transformFunction){ var result = [] for(var i=0;i<arr.length; i++){ result.push(transformFunction(arr[i])) } return result } //參數可以填匿名函式 console.log( transform([1,2,3],function(x){ return x*3 }) ) //輸出 : [3,6,9] ``` ___ ## 引數(Argument)與參數(Parameter) ```javascript= //引數跟參數,的名詞解釋 //參數 : 指函式括弧內的變數 //引數 : 指函式實際傳入的值 //範例1 : function add(a,b){ //a,b => 參數 return a+b } add(3,5) //3,5 => 引數 //範例2 : function add(a,b){ //a,b => 參數 return a+b } var c = 3 var d = 5 add(c,d) //3,5 => 引數,說c,d也行 //範例3 : //js特有的,可以在函式裡使用console.log(arguments),能印出引數,但很少用 function add(a,b){ //a,b => 參數 console.log(arguments) //能印出引數 return a+b } console.log(add(3,5)) //3,5 => 引數 //範例4 : function add(a,b){ //a,b => 參數 console.log(arguments[0]) //個別印出引數 console.log(arguments[1]) //個別印出引數 return a+b } console.log(add(3,5)) //3,5 => 引數 //範例5 : //還能這樣用,但通常不會這樣用 function add(){ return arguments[0]+arguments[1] } console.log(add(3,5)) //3,5 => 引數 ``` ___ ## Arguments 跟你想的不一樣 * Arguments : 是物件,但可以像陣列一樣使用 ```javascript= //範例 function add(a, b){ console.log(arguments.length) return a+b } console.log(add(3,5)) //物件也可以這麼使用 var a = { 0: 'hello' } console.log(a[0]) //印出123 ``` ___ ## 使用 function 時的注意事項 這次講的這個主題其實要講複雜的話可以講到很複雜,但我目前還不想談得那麼深,如果你真的很想知道,可以參考:[深入探討 JavaScript 中的參數傳遞:call by value 還是 reference?](https://blog.techbridge.cc/2018/06/23/javascript-call-by-value-or-reference/) * function傳參數的運作機制 * 此章節探討 : 在函式裡對引數重新賦值,外面變數是否會改變?物件,陣列會,數字,字串,布林不會,在使用上要注意。 * JavaScript 裡面只有 pass by value * JavaScript 的 primitive type 是 pass by value,object 是 pass by sharing ```javascript= //在函式裡對引數重新賦值,外面變數是否會改變?物件,陣列會 function addValue(obj){ obj.number++ return 1 } var a = { number : 10 } addValue(a) console.log(a) //輸出 => 11 ``` ```javascript= //在函式裡對引數重新賦值,外面變數是否會改變?函式內的物件以指向不同物件,不會改動到原本的 function addValue(obj){ obj.test = 1 return 1 } var a = { number : 10 } addValue(a) console.log(a) //輸出 => 10 ``` ___ ## return 不 return,有差嗎? * function return 預設為undefined * return底下寫的程式都不回執行 ```javascript= //不需要回傳結果,只需要他去執行 function sayHello(name){ console.log('hello',name) } sayHello('nick') //輸出 => hello nick ``` ```javascript= //不需要回傳結果,只需要他去執行 function sayHello(name){ //console.log('hello',name) } //像數學裡的y=f(x) var a = sayHello('nick') //輸出為sayHello('nick')的回傳值,函式return甚麼,a就是甚麼 console.log(a) //輸出 => undefined ``` ```javascript= //需要回傳結果 function double(x){ return x * 2 } var resule = double(3) console.log(resule) //輸出 => 6 ``` ___ # 常用的內建函式 ## Number 類型的內建函式 * 常用: * 無條件捨去 : Math.floor() * 無條件進位 : Math.ceil() * 4捨5入 : Math.round() * 取隨機數 : Math.random() * 數字轉字串 : Number(n),parseInt(n,10),parseFloat(n) * 字串轉數字 : * 開根號 : Math.sqrt() ```javascript= var a = 10; var b = '20'; //字串轉數字,Number(b) console.log(a+Number(b); //輸出 => 30 //字串轉數字(整數),parseInt(b,10),第二參數,可以放進制,範例為10進制 console.log(a+parseInt(b,10); //輸出 => 30 //字串轉數字(整數),parseInt(b,12),第二參數,可以放進制,範例為12進制 console.log(a+parseInt(b,12); //輸出 => 34 var a = 10; var b = '20.3545'; //字串轉數字(浮點數),parseFloat(b) console.log(parseFloat(b); //輸出 => 20.3545 //取小數第幾位,.toFixed(n),取小數第n位輸出,並4捨5入 console.log(parseFloat(b.toFixed(2)); //輸出 => 20.35 //取小數第幾位,.toFixed(n),取小數第n位輸出,並4捨5入,不填就小數點後都去掉 console.log( parseFloat(b.toFixed()); //輸出 => 20 //補充 : 浮點數精準度問題,在2進制裡表達無法精準 console.log(0.1+0.3 === 0.3) //輸出 => false //在javascript,能存的最大數,超出範圍,會不精準 console.log(Number.MAX_VALUE); //輸出 => 1.7976931348623157e+308 //在javascript,能存的最小數,超出範圍,會不精準 console.log(Number.MIN_VALUE); //輸出 => 5e-324 ``` ```javascript= //圓周率(PI),Math.PI,是常數,不會變,常數通常都用大寫,constant(恆定) console.log(Math.PI); //輸出 => 3.141592653589793 //無條件進位,Math.ceil() console.log(Math.ceil(10.1)) //輸出 => 11 //無條件捨去,Math.floor() console.log(Math.floor(10.9)) //輸出 => 10 //4捨5入,Math.round() console.log(Math.round(10.5)) //輸出 => 11 //開根號,Math.sqrt() console.log(Math.sqrt(9)) //輸出 => 9 //取次方,Math.pow() console.log(Math.pow(2,10)) //輸出 => 1024 //取隨機數,Math.random() console.log(Math.random()) //輸出 => 0到<1的數 //假設取0-9,隨機數 console.log(Math.floor(Math.random()*10)) //輸出 => 取0-9,隨機數 //假設取1-10,隨機數 console.log(Math.floor(Math.random()*10+1)) //輸出 => 取1-10,隨機數 //隨機數,公式 function getRandom(min,max){ return Math.floor(Math.random()*max)+min; }; //數字轉字串,.toString(),或+空字串,也能轉成字串 var a = 2 console.log(a.toString()) console.log(a+'') ``` [Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number) [Math](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math) ___ ## String 類型的內建函式 ```javascript= //小寫轉大寫,.toUpperCase() var str = 'abc'.toUpperCase() console.log(str) //輸出 => ABC //大寫轉小寫,.toLowerCase() var str = 'ABC'.toLowerCase() console.log(str) //輸出 => abc //將字串轉成ASCII碼中,所代表的10進制數字,.charCodeAt(n),n填要轉的字串,所在的位置 var str = 'A' var strCode = str.charCodeAt(0) console.log(strCode) //輸出 => 65 var str = 'a' var strCode = str.charCodeAt(0) console.log(strCode) //輸出 => 97 //數字轉ASCII碼中,對應的文字,String.formChaeCode() var str = String.fromCharCode(65) console.log(str) //輸出 => A //大寫跟小寫的數字差32 //小寫轉大寫-32 var char = 'g' var charCode = char.charCodeAt(0) var str = String.fromCharCode(charCode - 32) console.log(str) //輸出 => G //大寫轉小寫+32 var char = 'G' var charCode = char.charCodeAt(0) var str = String.fromCharCode(charCode + 32) console.log(str) //輸出 => g //如不知差32,也可以 var char = 'g' var charCode = char.charCodeAt(0) var str = String.fromCharCode(charCode - ('a'.charCodeAt(0) - 'A'.charCodeAt(0))) console.log(str) //輸出 => G //字串可以比較大小 var str = 'g' console.log(str >= 'a') //輸出 => true //比較是否在小寫a-z中 var str = 'g' console.log(str >= 'a' && str <= 'z') //輸出 => true //比較是否在大寫A-Z中 var str = 'G' console.log(str >= 'A' && str <= 'Z') //輸出 => true //尋找字串是否存在,是,回傳第一個字元所在位置,否,回傳-1,.indexOf() //主要檢查某字串是否存在此字串,如輸出>=0,有;如輸出-1,無 var str = 'hey hello world yoyoyo' var index = str.indexOf('hello') console.log(index) //輸出 => 4 var str = 'hey hello world yoyoyo' var index = str.indexOf('hello!!') console.log(index) //輸出 => -1 //取代某字串,.replace() var str = 'hey hello world yoyoyo'.replace('hey','!!!') console.log(str) //輸出 => !!! hello world yoyoyo //這樣使用只會換第一個 var str = 'hey hello world yoyoyo'.replace('y','!') console.log(str) //輸出 => he! hello world yoyoyo //如全都換要用,正規表達 var regex = /y/g; var str = 'hey hello world yoyoyo'.replace(regex,'!'); console.log(str) //輸出 => he! hello world !o!o!o //將字串切開並轉成陣列,split() var str = 'hey hello world yoyoyo'; console.log(str.split(' ')) //輸出 => [ 'hey', 'hello', 'world', 'yoyoyo' ] var str = 'data1,data2,data3,data4'; console.log(str.split(',')) //輸出 => [ 'data1', 'data2', 'data3', 'data4' ] //去除前後空格.trim() var str = ' data1,data2,data3,data4 '; console.log(str.trim()) //回傳字串長度,.length,這不是函式 var str = 'data1'; console.log(str.length) //輸出 => 5 ``` [String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) ___ ## Array 類型的內建函式 * 重要: * 對陣列個別元素做動作,回傳陣列 : .map() * 可以設條件過濾元素,為true,留下 : .filter() ```javascript= //將陣列轉字串,並中要穿插的符號,.join() var arr = [1, 2, 3]; var ary = ['data1', 'data2', 'data3']; console.log(arr.join('!')) //輸出 => 1!2!3 console.log(ary.join('!')) //輸出 => data1!data12!data3 //.map(),裡放函式,會對陣列個別元素做動作,回傳陣列 var arr = [1, 2, 3]; function double(x){ return x*2 } console.log(arr.map(double)) //輸出 => [ 2, 4, 6 ] //.filter(),可以設條件過濾元素,為true,留下 var arr = [1, 2, 3,-1,-2,-3]; function double(x){ return x*2 } console.log(arr .map(function(x){ return x*2 }) .filter(function(x){ return x<0 }) ) //輸出 => [ -2, -4, -6 ] //取陣列的某一部分,.slice(),第一參數放開始位置,第二參數放結束位置,結束位置那個也不要 //如無第二參數,預設切到最後 var arr = ['a', 'b', 'c', 'd'] console.log(arr.slice(1)) //輸出 => [ 'b', 'c', 'd' ] console.log(arr.slice(1,3)) //輸出 => [ 'b', 'c' ] //刪除跟新增元素,會改變原本的陣列 //會改變陣列,.splice(),第一參數放開始位置,第二參數放0or1,第三參數要插入的元素 //第二參數放0,會插入元素 //第二參數放1,刪除此位置元素,插入第三參數 var arr = ['a', 'b', 'c', 'd'] var ary = ['a', 'b', 'c', 'd'] arr.splice(2,0,'chage') ary.splice(2,1,'chage') console.log(arr) //輸出 => [ 'a', 'b', 'chage', 'c', 'd' ] console.log(ary) //輸出 => [ 'a', 'b', 'chage', 'd' ] //排序,.sort(),裡面可以放函式 //會照字串排列a-z,這順序 var arr = ['tony', 'nick', 'angela', 'boy'] arr.sort() console.log(arr) //輸出 => [ 'angela', 'boy', 'nick', 'tony' ] //照數字排序,要用函式 var arr = [1, 30, 4, 21] //規則 : 0 => a,b相等 ; -1 => a,b不換 ; 正整數 => a,b交換 //小到大 arr.sort(function(a,b){ if(a===b) return 0 //b>a?-1:1 if(b>a) return -1 return 1 }) console.log(arr) //輸出 => [ 1, 4, 21, 30 ] //大到小 arr.sort(function(a,b){ if(a===b) return 0 //a>b?-1:1 if(a>b) return -1 return 1 }) console.log(arr) //輸出 => [ 30, 21, 4, 1 ] //下面方式,等同上方 //小到大 arr.sort(function(a,b){ return a - b }) console.log(arr) //輸出 => [ 1, 4, 21, 30 ] //大到小 arr.sort(function(a,b){ return b - a }) console.log(arr) //輸出 => [ 30, 21, 4, 1 ] ``` ___ # 新手最會出錯的地方 ## 「回傳」與「印出」的差異 回傳 : return ,使用function,大多有回傳值 印出 : console.log(),大多都使用在function外,去顯使return出的值 ```javascript= function add(a,b){ return a+b //回傳 } console.log(add(10,20)) //印出 ``` ___ ## 超級無敵重要的 Immutable 觀念 * Immutable不可變 * 在呼叫function時,是會改變原來的值,還是回傳一個新的值,還是兩個都有,3種情況 * numder,string,原來的值不可變 * array,object,原來的值可變 ```javascript= //原來值不可變,需宣告新的變數做接收 var str = 'abc' str.toUpperCase() console.log(str) //輸出 => abc var strUpperCase = str.toUpperCase() //宣告新的變數去接收回傳值 console.log(strUpperCase) //輸出 => ABC //原來的值可變,還有回傳一個新的值 var arr = [1,2,3] var ary = arr.push(4) console.log(arr) //輸出 => [1,2,3,4] console.log(ary) //輸出 => 4 ``` ___ ## 拜託,請你愛用 console.log * 加console.log,可以方便找出bug ```javascript= //判斷是否是值質數,只有1跟自己是因數,就是質數 function isPrime(num){ if(num === 1) return false if(num === 2) return true for(var i=2; i<num; i++){ if(num % 2 === 0 ){ return false }else{ return true } } } console.log(isPrime(15)) //輸出 => true ``` ```javascript= //想看值的地方都加console.log function isPrime(num){ console.log('num:',num) //輸出 => num: 15 if(num === 1) return false if(num === 2) return true for(var i=2; i<=num; i++){ console.log('i:',i) //輸出 => i: 2 if(num % 2 === 0 ){ console.log('num % 2 === 0',num,i) return false }else{ console.log('elsec',num,i) //輸出 => elsec 15 2 return true } } } console.log(isPrime(15)) //輸出 => true //輸出 : num: 15 i: 2 elsec 15 2 true //根本只跑一次,i沒+到就return,還沒判斷3,4,5,6... ``` ```javascript= //正解,將return true,放在迴圈外 function isPrime(num){ if(num === 1) return false if(num === 2) return true for(var i=2; i<num; i++){ if(num % i === 0 ){ return false } } return true } console.log(isPrime(15)) ////輸出 => false ``` ___ # 綜合題目練習 Lv1 ## 練習一:印出一到九 ``` 請你分別用 for loop 以及 while 迴圈,印出 1~9。 預期輸出: 1 2 3 4 5 6 7 8 9 ``` ```javascript= //for for(var i=1; i<10; i++){ console.log(i) } //while var i=1 while(i<10){ console.log(i) i++ } //do while var i=1 do{ console.log(i) i++ }while(i<10) ``` ___ ## 練習二:寫一個能夠印出 1~n 的函式 ``` 請寫一個函式叫做 print,接收一個是數字的參數 n,並且印出 1~n。 print(1) 預期輸出: 1 print(3) 預期輸出: 1 2 3 print(9) 預期輸出: 1 2 3 4 5 6 7 8 9 ``` ```javascript= function print(n){ for(var i=1; i<=n; i++){ console.log(i) } } print(1) print(3) print(9) ``` ___ ## 練習三:寫一個能夠印出 n 個 * 的函式 ``` 寫一個函式 star,接收一個參數 n,並印出 n 個 * (禁止使用內建函式 repeat) star(1) 預期輸出: * star(5) 預期輸出: ***** star(10) 預期輸出: ********** ``` ```javascript= function star(n){ var str = '' for(var i=1; i<=n; i++){ str+='*' } console.log(str) } star(1) star(5) star(10) ``` ___ ## 練習四:寫一個能回傳 n 個 * 的函式 ``` 請寫出一個叫做 star 的 function 並且接受一個參數 n,能回傳 n 個 *。 star(1) 會回傳 * star(5) 會回傳 ***** 所以 console.log(star(5)) 的預期輸出是: ***** ``` ```javascript= function star(n){ var str = '' for(var i=1; i<=n; i++){ str+='*' } return str } console.log(star(5)) ``` ___ ## 練習五:判斷大小寫 ``` 請寫一個叫做 isUpperCase 的 functuon,並且接收一個字串,回傳這個字串的第一個字母是否為大寫。 isUpperCase("abcd") 正確回傳值:false isUpperCase("Abcd") 正確回傳值:true isUpperCase("ABCD") 正確回傳值:true isUpperCase("aBCD") 正確回傳值:false ``` ```javascript= function isUpperCase(str){ if(str[0] >= 'A' && str[0]<='Z'){ console.log(true) }else{ console.log(false) } } isUpperCase("abcd") //正確回傳值:false isUpperCase("Abcd") //正確回傳值:true isUpperCase("ABCD") //正確回傳值:true isUpperCase("aBCD") //正確回傳值:false ``` ___ ## 練習六:回傳第一個大寫字母以及它的 index ``` 請寫一個 function position,接收一個字串並回傳這個字串裡面的第一個大寫字母跟它的 index,若沒有則回傳 -1。 position("abcd") 正確回傳值:-1 position("AbcD") 正確回傳值:A 0 position("abCD") 正確回傳值:C 2 ``` ```javascript= function position(str){ for(var i=0; i<str.length; i++){ if(str[i] >= 'A' && str[i]<='Z'){ var s = true; break; } } if(s){ console.log(str[i]+' '+i) }else{ console.log(-1) } } position("abcd") //正確回傳值:-1 position("AbcD") //正確回傳值:A 0 position("abCD") //正確回傳值:C 2 ``` ___ ## 練習七:回傳陣列裡面所有小於 n 的數的數量 ``` 請寫出一個函式 findSmallCount,接收一個陣列跟一個數字 n,回傳有多少個數小於 n。 findSmallCount([1, 2, 3], 2) 預期回傳值:1 findSmallCount([1, 2, 3, 4, 5], 0) 預期回傳值:0 findSmallCount([1, 2, 3, 4], 100) 預期回傳值:4 ``` ```javascript= function findSmallCount(arr, num){ var s = [] for(var i=0; i<arr.length ; i++){ if(arr[i] < num){ s.push(arr[i]) } } console.log(s.length) } findSmallCount([1, 2, 3], 2) //預期回傳值:1 findSmallCount([1, 2, 3, 4, 5], 0) //預期回傳值:0 findSmallCount([1, 2, 3, 4], 100) //預期回傳值:4 ``` ___ ## 練習八:回傳陣列裡面所有小於 n 的數的總和 ``` 請寫一個函式 findSmallerTotal,接收一個陣列以及數字 n,回傳陣列裡面所有小於 n 的數的總和。 findSmallerTotal([1, 2, 3], 3) 正確回傳值:3 findSmallerTotal([1, 2, 3], 1) 正確回傳值:0 findSmallerTotal([3, 2, 5, 8, 7], 999) 正確回傳值:25 findSmallerTotal([3, 2, 5, 8, 7], 0) 正確回傳值:0 ``` ```javascript= function findSmallerTotal(arr, num){ var s = [] var a = 0 for(var i=0; i<arr.length ; i++){ if(arr[i] < num){ s.push(arr[i]) } } for(var j=0; j<s.length ; j++){ a+=s[j] } console.log(a) } findSmallerTotal([1, 2, 3], 3) //正確回傳值:3 findSmallerTotal([1, 2, 3], 1) //正確回傳值:0 findSmallerTotal([3, 2, 5, 8, 7], 999) //正確回傳值:25 findSmallerTotal([3, 2, 5, 8, 7], 0) //正確回傳值:0 ``` ___ ## 練習九:回傳陣列裡面所有小於 n 的數 ``` 請寫一個函式 findAllSmall,接收一個陣列跟一個數字 n,回傳一個裡面有所有小於 n 的數的陣列(需按照原陣列順序)。 findAllSmall([1, 2, 3], 10) 正確回傳值:[1, 2, 3] findAllSmall([1, 2, 3], 2) 正確回傳值:[1] findAllSmall([1, 3, 5, 4, 2], 4) 正確回傳值:[1, 3, 2] ``` ```javascript= function findAllSmall(arr, num){ var s = [] var a = 0 for(var i=0; i<arr.length ; i++){ if(arr[i] < num){ s.push(arr[i]) } } console.log(s) } findAllSmall([1, 2, 3], 10) //正確回傳值:[1, 2, 3] findAllSmall([1, 2, 3], 2) //正確回傳值:[1] findAllSmall([1, 3, 5, 4, 2], 4) //確回傳值:[1, 3, 2] ``` ___ ## 練習十:回傳陣列總和 ``` 請寫一個 function sum,接收一個陣列並回傳陣列中數字的總和。 sum([1, 2, 3]) 預期回傳值:6 sum([-1, 1, 2, -2, 3, -3]) 預期回傳值:0 ``` ```javascript= function sum(arr){ var s = 0 for(var i=0; i<arr.length ; i++){ s+=arr[i] } console.log(s) } sum([1, 2, 3]) //預期回傳值:6 sum([-1, 1, 2, -2, 3, -3]) //預期回傳值:0 ``` ___ # 綜合題目練習 Lv2 ## 練習一:好多星星 ``` 請寫出一個 function stars,接收一個參數 n,並且按照規律印出相對應的圖案。 stars(1) 預期輸出: * stars(3) 預期輸出: * ** *** stars(7) 預期輸出: * ** *** **** ***** ****** ******* ``` ```javascript= function stars(n){ var s ='' for(var i=1; i<=n; i++){ for(var j=1; j<=i; j++){ s+='*' } console.log(s) s ='' } } stars(1) stars(3) stars(7) ``` ___ ## 練習二:好多星星 回傳版 ``` 請寫出一個 function makeStars,接收一個參數 n,並且根據規律「回傳」字串 makeStars(1) 正確回傳值:* makeStars(2) 正確回傳值:*\n** makeStars(5) 正確回傳值:*\n**\n***\n****\n***** ``` ```javascript= function makeStars(n){ var str = '' var arr = [] for(var i=1; i<=n; i++){ for(var j=1; j<=i; j++){ str+='*' } arr.push(str) str = '' } console.log(arr.join('\\n')) } makeStars(1) //正確回傳值:* makeStars(2) //正確回傳值:*\n** makeStars(5) //正確回傳值:*\n**\n***\n****\n***** ``` ___ ## 練習三:好多星星 加強版 ``` 請寫出一個函式 stars2,接收一個參數 n,並依照規律印出圖形。 stars2(1) 預期輸出: * stars2(3) 預期輸出: * ** *** ** * stars2(5) 預期輸出: * ** *** **** ***** **** *** ** * ``` ```javascript= function stars2(n){ var s ='' for(var i=1; i<=n; i++){ for(var j=1; j<=i; j++){ s+='*' } console.log(s) s ='' } for(var i=n-1; i>0; i--){ for(var j=i; j>0; j--){ s+='*' } console.log(s) s ='' } } stars2(1) stars2(3) stars2(5) ``` ___ ## 練習四:乘法表 ``` 請寫一個函式 table,接收一個數字 n,印出 n*1 ~ n*9 的結果。 table(1) 預期輸出: 1*1 = 1 1*2 = 2 1*3 = 3 1*4 = 4 1*5 = 5 1*6 = 6 1*7 = 7 1*8 = 8 1*9 = 9 table(7) 預期輸出: 7*1 = 1 7*2 = 14 7*3 = 21 7*4 = 28 7*5 = 35 7*6 = 42 7*7 = 49 7*8 = 56 7*9 = 63 ``` ```javascript= function table(n){ for(var i=1; i<=9; i++){ console.log(n,'*',i,'=',n*i) //console.log(n+'*'+i+'='+n*i) } } table(1) table(7) ``` ___ ## 練習五:九九乘法表 ``` 請寫出一個 function table9to9,並列出 1*1 ~ 9*9。 table9to9() 預期輸出: 1*1 = 1 1*2 = 2 1*3 = 3 ..... 5*1 = 5 5*2 = 10 5*3 = 15 .... 9*7 = 63 9*8 = 72 9*9 = 81 ``` ```javascript= function table9to9(){ for(var i=1; i<=9; i++){ for(var j=1; j<=9; j++){ console.log(i,'*',j,'=',i*j) } console.log('.....') } } table9to9() ``` ___ ## 練習六:費式數列 ``` 費式數列的定義為:第 n 個數等於前兩個數的總和,因此這個數列會長的像這樣:1 1 2 3 5 8 13 21 .... 用比較數學一點的講法,就是: fib(0) = 0 fib(1) = 1 for n >=2, fib(n) = fib(n-1) + fib(n-2) 現在,請你寫出一個 fib 的函式,回傳位在第 n 個位置的數字 fib(1) 預期回傳值:1 fib(2) 預期回傳值:1 fib(8) 預期回傳值:21 ``` ```javascript= function fib(n) { const result = [0, 1]; for (let index = 2; index <= n; index++) { // 倒數第一個數 const a = result[index - 1]; // or result[result.length -1] // 倒數第二個數 const b = result[index - 2]; result.push(a + b); } //console.log('full array: ' + result) console.log('last number: ' + result[result.length -1]) return result[result.length -1]; } fib(1) //預期回傳值:1 fib(2) //預期回傳值:1 fib(8) //預期回傳值:21 ``` ___ ## 練習七:字串反轉 ``` 請寫出一個函式 reverse,接收一個字串,並且回傳反轉過後的字串。(禁止使用內建函式 reverse) reverse("abcd") 預期回傳值:dcba reverse("12345aa") 預期回傳值:aa54321 ``` ```javascript= function reverse(str){ var strRerverse = '' for(var i = str.length - 1; i>=0; i-- ){ strRerverse += str[i] } console.log(strRerverse) } reverse("abcd") //預期回傳值:dcba reverse("12345aa") //預期回傳值:aa54321 ``` ___ ## 練習八:大小寫互換 ``` 請寫一個函式 swap,接收一個字串,並且回傳大小寫互換後的字串。 swap("Peter") 預期回傳值:pETER swap("AbCdE") 預期回傳值:aBcDe ``` ```javascript= function swap(str){ var strSwap = '' for(var i=0; i<=str.length; i++){ if(str[i] >= 'a' && str[i] <= 'z'){ strSwap += str[i].toUpperCase(); }else if(str[i] >= 'A' && str[i] <= 'Z'){ strSwap += str[i].toLowerCase(); } } console.log(strSwap) } swap("Peter") //預期回傳值:pETER swap("AbCdE") //預期回傳值:aBcDe ``` ___ ## 練習九:找出最小值 ``` 請寫出一個函式 findMin,接收一個陣列並回傳陣列中的最小值。(禁止使用內建函式 sort) findMin([1, 2, 5, 6, 99, 4, 5]) 預期回傳值:1 findMin([1, 6, 0, 33, 44, 88, -10]) 預期回傳值:-10 ``` ```javascript= function findMin(arr){ var Min = arr[0] for(var i=1; i<arr.length; i++){ if(arr[i] < Min){ Min = arr[i] } } console.log(Min) } findMin([1, 2, 5, 6, 99, 4, 5]) //預期回傳值:1 findMin([1, 6, 0, 33, 44, 88, -10]) //預期回傳值:-10 ``` ___ ## 練習十:找出第 n 小的值 ``` 這題是上一題的加強版,上一題只要你找出最小值,而這一題請你寫一個 function findNthMin,接收一個陣列以及一個數字 n,找出第 n 小的數字。(禁止使用內建函式 sort) 提示:假設我要找出第 2 小的值,我只要先找出最小的值然後再把它刪掉,再重新找一次最小的值,就會是第 2 小的值了。 findNthMin([1, 2, 3, 4, 5], 1) 預期回傳值:1 findNthMin([1, 3, 5, 7, 9], 3) 預期回傳值:5 findNthMin([1, 1, 1, 1, 1], 2) 預期回傳值:1 ``` ```javascript= function findNthMin(arr,n){ for(var i=0; i<arr.length; i++){ var Min = arr[i]; var MinIndex = i; for(var j=i; j<arr.length; j++){ if(arr[j] < Min ){ Min = arr[j]; MinIndex = j; } } [arr[MinIndex], arr[i]] = [arr[i], arr[MinIndex]]; } console.log(arr[n-1]) } findNthMin([1, 2, 3, 4, 5], 1) //預期回傳值:1 findNthMin([1, 3, 5, 7, 9], 3) //預期回傳值:5 findNthMin([1, 1, 1, 1, 1], 2) //預期回傳值:1 ``` ___ # 綜合題目練習 Lv3 ## 練習一:排序 ``` 請寫一個 function sort,接收一個陣列並且回傳由小到大排序後的陣列。(禁止使用內建函式 sort) 提示:如果你已經會找第 n 小的值了,試著把這個概念應用到這題上。 sort([ 6, 8, 3, 2]) 預期回傳值:[2, 3, 6, 8] sort([ 1, 2, 7 ,5]) 預期回傳值:[1, 2, 5, 7] ``` ```javascript= function sort(arr,n){ for(var i=0; i<arr.length; i++){ var Min = arr[i]; var MinIndex = i; for(var j=i; j<arr.length; j++){ if(arr[j] < Min ){ Min = arr[j]; MinIndex = j; } } [arr[MinIndex], arr[i]] = [arr[i], arr[MinIndex]]; } console.log(arr) } sort([ 6, 8, 3, 2]) //預期回傳值:[2, 3, 6, 8] sort([ 1, 2, 7 ,5]) //預期回傳值:[1, 2, 5, 7] ``` ___ ## 練習二:壓平陣列 ``` 請寫出一個 function flatten,接收一個多維陣列並回傳「壓平」後的陣列。 flatten([1, 2, 3]) 預期回傳值:[1, 2, 3] flatten([1, 2, [1, 2], [1, 3], 6]) 預期回傳值:[1, 2, 1, 2, 1, 3, 6] flatten([1, [2, [3, [4]], 5], 6]) 預期回傳值:[1, 2, 3, 4, 5, 6] ``` ```javascript= function flatten(arr){ var arr1 = (arr + '').split(',');//將數組轉字符串後再以逗號分隔轉為數組 var arr2 = arr1 .map(function(x){ return Number(x); }); console.log(arr2); } flatten([1, 2, 3]) //預期回傳值:[1, 2, 3] flatten([1, 2, [1, 2], [1, 3], 6]) //預期回傳值:[1, 2, 1, 2, 1, 3, 6] flatten([1, [2, [3, [4]], 5], 6]) //預期回傳值:[1, 2, 3, 4, 5, 6] ``` ___ ## 練習三:印出聖誕樹 ``` 請寫一個 function tree,接收一個數字 n,按照規律列印出大小為 n 的聖誕樹 (這邊編輯器有點問題空白顯示不出來,用 _ 代表空白) tree(1) 預期輸出: * tree(2) 預期輸出: _* *** _* _* tree(5) 預期輸出: ____* ___*** __***** _******* ********* ____* ____* ____* ____* ____* ``` ```javascript= function tree(n){ var str = '' var str1 = '' for(var k=0; k<n; k++){ for(var i=k; i<n-1; i++){ str+='_' } for(var j=0; j<(k*2)+1; j++){ str+='*' } if(k == 0){ str1 = str } console.log(str) str = '' } if(n>1){ for(var l=0; l<n; l++){ console.log(str1) } } } tree(1) tree(3) tree(5) ``` ___ ## 練習四:判斷圈圈叉叉勝負 ``` 請寫出一個 function winner,接收一個代表圈圈叉叉的陣列,並回傳贏的是 O 還是 X,如果平手或還沒下完,請回傳 draw。 winner([ ['O', 'O', 'X'], ['O', 'X', 'X'], ['O', 'X', 'O'] ]) 預期回傳值:O winner([ ['O', 'O', 'X'], ['O', 'X', 'X'], ['X', 'X', 'O'] ]) 預期回傳值:X winner([ ['O', 'O', 'X'], ['O', 'O', 'X'], ['X', 'X', ''] ]) 預期回傳值:draw ``` ```javascript= function winner(arr){ var draw = '' for(var i=0; i<3; i++){ if(arr[i][0] == arr[i][1] && arr[i][1] == arr[i][2]){ draw = arr[i][0] console.log(arr[i][0]) }else if(arr[0][i] == arr[1][i] && arr[1][i] == arr[2][i]){ draw = arr[0][i] console.log(arr[0][i]) } } if(arr[0][0] == arr[1][1] && arr[1][1] == arr[2][2]){ draw = arr[1][1] console.log(arr[1][1]) }else if(arr[0][2] == arr[1][1] && arr[1][1] == arr[2][0]){ draw = arr[1][1] console.log(arr[1][1]) }else if(draw == ''){ console.log('draw') } } winner([ ['O', 'O', 'X'], ['O', 'X', 'X'], ['O', 'X', 'O'] ]) //預期回傳值:O winner([ ['O', 'O', 'X'], ['O', 'X', 'X'], ['X', 'X', 'O'] ]) //預期回傳值:X winner([ ['O', 'O', 'X'], ['O', 'O', 'X'], ['X', 'X', ''] ]) //預期回傳值:draw ``` ___ ## 練習五:判斷質數 ``` 請寫出一個 function isPrime,給定一個數字 n,回傳 n 是否為質數。 (質數的定義:除了 1 以外,沒辦法被所有 < n 的正整數整除) isPrime(1) 正確回傳值:false isPrime(5) 正確回傳值:true isPrime(37) 正確回傳值:true ``` ```javascript= function isPrime(num){ if(num === 1){ console.log(false) return false } if(num === 2){ console.log(true) return (true) } for(var i=2; i<num; i++){ if(num % i === 0 ){ console.log(false) return false } } console.log(true) return true } isPrime(1) //正確回傳值:false isPrime(5) //正確回傳值:true isPrime(37) //正確回傳值:trues ``` ___ # 請自己想過、試過再來看這些講解影片 ## 綜合題目練習 Lv1 ### 練習一:印出一到九 ```javascript= var i = 1 while(i<=9){ console.log(i) i++ } ``` ```javascript= var i = 1 do{ console.log(i) i++ }while(i<=9) ``` ```javascript= for(var i=1; i<=9; i++){ console.log(i) } ``` ___ ### 練習二:寫一個能夠印出 1~n 的函式 ```javascript= function print(n){ for(var i=1; i<=n; i++){ console.log(i) } } print(1) print(3) print(9) ``` ___ ### 練習三:寫一個能夠印出 n 個 * 的函式 ```javascript= //補充 : .repeat(n),使字串*n次,輸出成新字串 var str = "Runoob"; str1 = str.repeat(2); console.log(str1) //RunoobRunoob ``` ```javascript= function star(n){ var answer = '' for(var i=1; i<=n; i++){ answer+='*' } console.log(answer) } star(1) star(5) star(10) ``` ```javascript= //補充 : 印出 n 個 ? 的函式,?可以填任意符號 function star(str,n){ var answer = '' for(var i=1; i<=n; i++){ answer+=str } console.log(answer) } star('!',1) star('+',5) star('?',10) ``` ___ ### 練習四:寫一個能回傳 n 個 * 的函式 * 此題比較,印出跟回傳的不同 ```javascript= function star(n){ var answer = '' for(var i=1; i<=n; i++){ answer+='*' } return answer } console.log(star(5)) ``` ___ ### 練習五:判斷大小寫 ```javascript= //方法1 : function isUpperCase(str){ var char = str[0] if(char >= 'a' && char <='z') return false if(char >= 'A' && char <='Z') return true } console.log(isUpperCase("abcd")) //正確回傳值:false console.log(isUpperCase("Abcd")) //正確回傳值:true console.log(isUpperCase("ABCD")) //正確回傳值:true console.log(isUpperCase("aBCD")) //正確回傳值:false ``` ```javascript= //方法2 : function isUpperCase(str){ var char = str[0] if(char >= 'A' && char <='Z') return true return false } console.log(isUpperCase("abcd")) //正確回傳值:false console.log(isUpperCase("Abcd")) //正確回傳值:true console.log(isUpperCase("ABCD")) //正確回傳值:true console.log(isUpperCase("aBCD")) //正確回傳值:false ``` ```javascript= //方法3 : functㄎion isUpperCase(str){ var char = str[0] return char >= 'A' && char <='Z' } console.log(isUpperCase("abcd")) //正確回傳值:false console.log(isUpperCase("Abcd")) //正確回傳值:true console.log(isUpperCase("ABCD")) //正確回傳值:true console.log(isUpperCase("aBCD")) //正確回傳值:false ``` ___ ### 練習六:回傳第一個大寫字母以及它的 index ```javascript= function position(str){ for(var i=0; i<=str.length; i++){ if(str[i] >='A' && str[i]<='Z'){ return str[i] + ' ' + i } } return -1 } console.log(position("abcd")) //正確回傳值:-1 console.log(position("AbcD")) //正確回傳值:A 0 console.log(position("abCD")) //正確回傳值:C 2 ``` ___ ### 練習七:回傳陣列裡面所有小於 n 的數的數量 ```javascript= //方法1 : function findSmallCount(arr, n){ var counter = 0 for(var i=0; i<arr.length ; i++){ if(arr[i] < n) counter++ } return counter } console.log(findSmallCount([1, 2, 3], 2)) //預期回傳值:1 console.log(findSmallCount([1, 2, 3, 4, 5], 0)) //預期回傳值:0 console.log(findSmallCount([1, 2, 3, 4], 100)) //預期回傳值:4 ``` ```javascript= //方法2 : function findSmallCount(arr, n){ return arr.filter(function(item){ return item <n }).length } console.log(findSmallCount([1, 2, 3], 2)) //預期回傳值:1 console.log(findSmallCount([1, 2, 3, 4, 5], 0)) //預期回傳值:0 console.log(findSmallCount([1, 2, 3, 4], 100)) //預期回傳值:4 ``` ___ ### 練習八:回傳陣列裡面所有小於 n 的數的總和 ```javascript= function findSmallerTotal(arr, n){ var sum = 0 for(var i=0; i<arr.length ; i++){ if(arr[i] < n) sum+=arr[i] } return sum } console.log(findSmallerTotal([1, 2, 3], 3)) //正確回傳值:3 console.log(findSmallerTotal([1, 2, 3], 1)) //正確回傳值:0 console.log(findSmallerTotal([3, 2, 5, 8, 7], 999)) //正確回傳值:25 console.log(findSmallerTotal([3, 2, 5, 8, 7], 0)) //正確回傳值:0 ``` ___ ### 練習九:回傳陣列裡面所有小於 n 的數 ```javascript= function findAllSmall(arr, n){ var answer = [] for(var i=0; i<arr.length ; i++){ if(arr[i] < n) answer.push(arr[i]) } return answer } console.log(findAllSmall([1, 2, 3], 10)) //正確回傳值:[1, 2, 3] console.log(findAllSmall([1, 2, 3], 2)) //正確回傳值:[1] console.log(findAllSmall([1, 3, 5, 4, 2], 4)) //確回傳值:[1, 3, 2] ``` ___ ### 練習十:回傳陣列總和 更正:影片裡面有提到 reduce 的 initialValue 沒給的話,accumulator 的初始值就會是 null,這是不正確的 正確的行為是:accumulator 的初始值會是陣列的第一個元素,詳情可參考 MDN >[Array](https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce) ```javascript= //方法1 : function sum(arr){ var answer = 0 for(var i=0; i<arr.length; i++){ answer += arr[i] } return answer } console.log(sum([1, 2, 3])) //預期回傳值:6 console.log(sum([-1, 1, 2, -2, 3, -3])) //預期回傳值:0 ``` >//.reduce( ),函式介紹,( )內可以傳入function,並有兩個參數,==參數accumulator==初始值為陣列的第一個元素,運算return後的值為==currentValue + accumulator==,==參數accumulator = return後 currentValue + accumulator的值==,因此也可以應用在運算陣列總和上,當然還有許多使用的時機。 > >[1, 2, 3].reduce( function(==accumulator==, currentValue){ return currentValue + accumulator }, ==accumulator初始值==) > >==accumulator==,這參數,就像是儲存程式中,某一種狀態的意思 > ```javascript= //方法2 : 利用.map() function sum(arr){ var ans = 0 arr.map(function(value){ ans = ans + value return value }) return ans } console.log(sum([1, 2, 3])) //預期回傳值:6 console.log(sum([-1, 1, 2, -2, 3, -3])) //預期回傳值:0 ``` ```javascript= //方法3 : 利用.forEach(),一樣會跑每一個元素,但不用return 元素回去 function sum(arr){ var ans = 0 arr.forEach(function(value){ ans = ans + value }) return ans } console.log(sum([1, 2, 3])) //預期回傳值:6 console.log(sum([-1, 1, 2, -2, 3, -3])) //預期回傳值:0 ``` ```javascript= ///方法4 : .reduce() function sum(arr){ return arr.reduce(function(total, value){ return total + value }) } console.log(sum([1, 2, 3])) //預期回傳值:6 console.log(sum([-1, 1, 2, -2, 3, -3])) //預期回傳值:0 ``` ```javascript= //.reduce(),其他範例 //return obj的意思,就是設計如何去改obj,這元素 console.log( [1, 2, 3].reduce( function(obj, value){ obj['a'+value] = value return obj },{} ) ) //{ a1: 1, a2: 2, a3: 3 } ``` ```javascript= //.reduce(),其他範例,小於n值的數量 console.log( [1, 2, 3, 4, 5, 10, 20].reduce( function(count, value){ if(value < 5) count++ return count },0 ) ) //4 ``` ```javascript= //.reduce(),其他範例,小於n值的總和 console.log( [1, 2, 3, 4, 5, 10, 20].reduce( function(count, value){ if(value < 5) return count + value return count },0 ) ) //10 ``` ___ ## 綜合題目練習 Lv2 ### 練習一:好多星星 ```javascript= //方法1 : 分解成多的function解決問題 function printStar(n){ var result = '' for(var i=1; i<=n; i++){ result+='*' } console.log(result) } function stars(n){ for(var i=1; i<=n; i++){ printStar(i) } } stars(1) stars(3) stars(7) ``` ```javascript= //方法1 : 雙迴圈 function stars(n){ for(var i=1; i<=n; i++){ var result = '' for(var j=1; j<=i; j++){ result+='*' } console.log(result) } } stars(1) stars(3) stars(7) ``` ___ ### 練習二:好多星星 回傳版 ```javascript= //方法1 : 字串 function star(i){ var result = '' for(var j=1; j<=i; j++){ result+='*' } return result } function makeStars(n){ var result = '' for(var i=1; i<=n; i++){ result += star(i) if(i !== n){ result += '\n' } } return result } console.log(makeStars(1)) console.log(makeStars(2)) console.log(makeStars(5)) ``` ```javascript= //方法2 : 陣列 function star(i){ var result = '' for(var j=1; j<=i; j++){ result+='*' } return result } function makeStars(n){ var arr = [] for(var i=1; i<=n; i++){ arr.push(star(i)) } return arr.join('\n') } console.log(makeStars(1)) console.log(makeStars(2)) console.log(makeStars(5)) ``` ```javascript= //方法3 : 陣列 function star(i){ var result = '' for(var j=1; j<=i; j++){ result+='*' } return result } function makeStars(n){ return Array(n).fill(0).map(function(value, index){ return star(index + 1) }).join('\n') } console.log(makeStars(1)) console.log(makeStars(2)) console.log(makeStars(5)) ``` ___ ### 練習三:好多星星 加強版 ```javascript= //方法1 : function star(i){ var result = '' for(var j=1; j<=i; j++){ result+='*' } return result } function stars2(n){ for(var i=1; i<=n; i++){ console.log(star(i)) } for(var i=n-1; i>=1; i--){ console.log(star(i)) } } stars2(1) stars2(3) stars2(5) ``` ```javascript= //方法2 : function stars2(n){ for(var i=1; i<=n; i++){ var result = '' for(var j=1; j<=i; j++){ result+='*' } console.log(result) } for(var i=n-1; i>=1; i--){ var result = '' for(var j=1; j<=i; j++){ result+='*' } console.log(result) } } stars2(1) stars2(3) stars2(5) ``` ___ ### 練習四:乘法表 ```javascript= function table(n){ for(var i=1; i<=9; i++){ console.log(n + '*' + i + '=' + n*i) } } table(1) table(7) ``` ___ ### 練習五:九九乘法表 ```javascript= //方法1 : function table(n){ for(var i=1; i<=9; i++){ console.log(n + '*' + i + '=' + n*i) } } function table9to9(n){ for(var i=1; i<=9; i++){ table(i) } } table9to9() ``` ```javascript= //方法2 : function table9to9(n){ for(var i=1; i<=9; i++){ for(var j=1; j<=9; j++){ console.log(i + '*' + j + '=' + i*j) } } } table9to9() ``` ___ ### 練習六:費式數列 ```javascript= //方法1 : 遞迴 function fib(n){ if(n === 0) return 0 if(n === 1) return 1 return fib( n-2 ) + fib( n-1 ) } console.log(fib(8)) ``` ```javascript= //方法2 : 陣列 function fib(n){ var fib = [0,1] for(var i=2; i<=n; i++){ fib[i] = fib[i-1] + fib[i-2] } return fib[n] } console.log(fib(8)) ``` ___ ### 練習七:字串反轉 ```javascript= function reverse(str){ var reverseStr = '' for(var i=str.length-1; i>=0 ;i--){ reverseStr+=str[i] } return reverseStr } console.log(reverse("abcd")) console.log(reverse("12345aa")) ``` ___ ### 練習八:大小寫互換 ```javascript= //方法1 : 字串 function swap(str){ var result = '' for(var i=0; i<str.length; i++){ if(str[i] >= 'a' && str[i] <= 'z'){ result += str[i].toUpperCase(); }else if(str[i] >= 'A' && str[i] <= 'Z'){ result += str[i].toLowerCase(); }else{ result += str[i] } } return result } console.log(swap("Peter")) console.log(swap("AbCdE")) ``` ```javascript= //方法2 : function swap(str){ var result = '' for(var i=0; i<str.length; i++){ if(str[i] >= 'a' && str[i] <= 'z'){ result += str[i].toUpperCase(); }else if(str[i] >= 'A' && str[i] <= 'Z'){ result += str[i].toLowerCase(); } } return result } console.log(swap("Peter")) console.log(swap("AbCdE")) ``` ```javascript= //方法3 : 陣列 function swap(str){ return str.split('').map(function(char){ if(char >= 'a' && char <= 'z'){ return char.toUpperCase(); } return char.toLowerCase() }).join('') } console.log(swap("Peter")) console.log(swap("AbCdE")) ``` ```javascript= //方法4 : 陣列 function swap(str){ return str.split('').map(function(char){ return (char >= 'a' && char <= 'z') ? char.toUpperCase() : char.toLowerCase() }).join('') } console.log(swap("Peter")) console.log(swap("AbCdE")) ``` ```javascript= //方法5 : 陣列 function swap(str){ return str.split('').map(function(char){ return char[(char >= 'a' && char <= 'z') ? 'toUpperCase' : 'toLowerCase']() }).join('') } console.log(swap("Peter")) console.log(swap("AbCdE")) ``` ___ ### 練習九:找出最小值 ```javascript= //方法1 : function isSmallest(arr, number){ return arr.filter(function(item){ return item < number }).length === 0 } function findMin(arr){ for(var i=0; i<arr.length; i++){ if(isSmallest(arr,arr[i])){ return arr[i] } } } console.log(findMin([1, 2, 5, 6, 99, 4, 5])) console.log(findMin([1, 6, 0, 33, 44, 88, -10])) ``` ```javascript= //方法2 : function findMin(arr){ var Min = arr[0] for(var i=1; i<arr.length; i++){ if( Min > arr[i]){ Min = arr[i] } } return Min } console.log(findMin([1, 2, 5, 6, 99, 4, 5])) console.log(findMin([1, 6, 0, 33, 44, 88, -10])) ``` ___ ### 練習十:找出第 n 小的值 ```javascript= //方法1 : function findMin(arr){ var Min = arr[0] var MinIndex = 0 for(var i=1; i<arr.length; i++){ if( Min > arr[i]){ Min = arr[i] MinIndex = i } } return MinIndex } function findNthMin(arr, nth){ for(var i=1; i<=nth-1; i++){ var MinIndex = findMin(arr) arr.splice(MinIndex, 1) } var MinIndex = findMin(arr) return arr[MinIndex] } console.log(findNthMin([1, 2, 3, 4, 5], 1)) console.log(findNthMin([1, 3, 5, 7, 9], 3)) console.log(findNthMin([1, 1, 1, 1, 1], 2)) ``` ```javascript= //方法2 : function findMin(arr){ var Min = arr[0] var MinIndex = 0 for(var i=1; i<arr.length; i++){ if( Min > arr[i]){ Min = arr[i] MinIndex = i } } return MinIndex } function findNthMin(arr, nth){ for(var i=1; i<=nth-1; i++){ var MinIndex = findMin(arr) arr = arr.filter(function(item, index){ return index !== MinIndex }) } var MinIndex = findMin(arr) return arr[MinIndex] } console.log(findNthMin([1, 2, 3, 4, 5], 1)) console.log(findNthMin([1, 3, 5, 7, 9], 3)) console.log(findNthMin([1, 1, 1, 1, 1], 2)) ``` ___ ## 綜合題目練習 Lv3 ### 練習一:排序 ```javascript= function findMin(arr){ var Min = arr[0] var MinIndex = 0 for(var i=1; i<arr.length; i++){ if( Min > arr[i]){ Min = arr[i] MinIndex = i } } return MinIndex } function sort(arr){ var result = [] var length = arr.length for(var i=0; i<length; i++){ var MinIndex = findMin(arr) result.push(arr[MinIndex]) arr.splice(MinIndex, 1) } return result } console.log(sort([ 6, 8, 3, 2])) console.log(sort([ 1, 2, 7 ,5])) ``` ___ ### 練習二:壓平陣列 補充一下,這題的經典錯誤解法就是用 join 之後再去 split 為什麼呢? 這招如果輸入都是數字的話是可以的,但如果輸入不是呢?題目並沒有說輸入都是數字,只是給的範例剛好都是 例如說 flatten([',', '123', '4,5']),join 再 split 就不管用了 ```javascript= function flatten(arr){ var result = [] for(var i=0; i<arr.length; i++){ if(Array.isArray(arr[i])){ var flatArr = flatten(arr[i]) flatArr.forEach(function(value){ result.push(value) }) }else{ result.push(arr[i]) } } return result } console.log(flatten([1, 2, 3])) //預期回傳值:[1, 2, 3] console.log(flatten([1, 2, [1, 2], [1, 3], 6])) //預期回傳值:[1, 2, 1, 2, 1, 3, 6] console.log(flatten([1, [2, [3, [4]], 5], 6])) //預期回傳值:[1, 2, 3, 4, 5, 6] ``` ___ ### 練習三:印出聖誕樹 ```javascript= function tree(n){ if(n===1) return console.log('*') ptintTreeTop(n) ptintTreeBottom(n) } function ptintTreeTop(n){ for(var i=1; i<=n; i++){ console.log(' '.repeat(n-i) + '*'.repeat(2*i-1)) } } function ptintTreeBottom(n){ for(var i=1; i<=n; i++){ console.log(' '.repeat(n-1) + '*') } } tree(10) ``` ___ ### 練習四:判斷圈圈叉叉勝負 ```javascript= function winner(arr){ for(var i=0; i<3; i++){ //橫排 if(arr[i][0] == arr[i][1] && arr[i][1] == arr[i][2]){ return arr[i][0] } //直排 if(arr[0][i] == arr[1][i] && arr[1][i] == arr[2][i]){ return arr[0][i] } } if(arr[0][0] == arr[1][1] && arr[1][1] == arr[2][2]){ return arr[1][1] } if(arr[0][2] == arr[1][1] && arr[1][1] == arr[2][0]){ return arr[1][1] } return 'draw' } console.log( winner([ ['O', 'O', 'X'], ['O', 'X', 'X'], ['O', 'X', 'O'] ])) //預期回傳值:O console.log( winner([ ['O', 'O', 'X'], ['O', 'X', 'X'], ['X', 'X', 'O'] ])) //預期回傳值:X console.log( winner([ ['O', 'O', 'X'], ['O', 'O', 'X'], ['X', 'X', ''] ])) //預期回傳值:draw ``` ___ ### 練習五:判斷質數 ```javascript= //方法1 : function isPrime(n){ if(n === 1) return false for(var i=2; i<=n-1; i++){ if(n%i===0){ return false } } return true } for(var i=1; i<=50; i++){ if(isPrime(i)) console.log(i) } ``` ```javascript= //方法2 : function isPrime(n){ if(n === 1) return false for(var i=2; i<=Math.sqrt(n); i++){ if(n%i===0){ return false } } return true } for(var i=1; i<=50; i++){ if(isPrime(i)) console.log(i) } ``` ___ # 總結 解題時,應該有的思考方式,將大問題切割成多個小問題,會越來越好解決,如碰到邏輯想不通時: * 第一步,用中文將解題步驟寫下來。 * 第二步,將中文換成function名稱。 * 第三步,去function裡實作,那些細節,如把解題流程拆的越細,解的越快,如果寫久了,就不用拆成function,也能一次寫完。