# [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,也能一次寫完。