一、條件分支語句
條件分支語句,也叫作條件判斷語句,就是根據某種條件執行某些語句,不執行某些語句。
JS中有三種語法是可以表示條件分支的
1.1 if……else……
條件分支的主力語法,這個主力語法能夠書寫所有的條件分支語句。也就是說,一會兒學switch case語句,switch case語句能幹的,if else語句一定也能幹。
標準的完整結構:
if(){ }else if(){ }else if(){ }else{ }
else只能有一個,並且一定要放在最後。表示所有的分支都不滿足的時候執行的事情。
可以沒有else:
if(){ }else if(){ }else if(){ }
可以沒有分支:
if(){
} |
看準樓的位置:
if(8 > 5){ console.log("哈哈"); } console.log("嘻嘻"); //這行語句不在if裡,所以不管if成功沒有,都執行 |
如果只有一行語句,那麼就可以省略大括號:
if(8 > 15) console.log("哈哈"); console.log("嘻嘻"); |
跳樓現象,要會合理利用。
var a = 4; if(a < 8){ a++; //a變為5,然後跳樓,不會進行下面的a==5的比較了 }else if(a == 5){ a++; } console.log(a); //5
1.2 switch case語句
也叫開關語句,開關語句執行一個程式求一個表示式的值,並且嘗試去匹配表示式的值到一個case標籤,如果匹配成功,這個程式執行相關語句。Switch語句能做的,if語句一定能做。
switch:關鍵字
case:匹配案例
break:打斷程式碼,跳出整個switch語句
default:相當於if語句中的else,否則的情況。
語法:
switch(待檢測值){ case 值1 : 值1 與 待檢測值 匹配時執行 break; case 值2 : 值2 與 待檢測值 匹配時執行 break; case 值3 : 值3 與 待檢測值 匹配時執行 break; default : 待檢測的值與前面的case都不匹配時執行 break; }
Default:相當於if語句中的else,default也可以不寫,如果前面都不匹配,直接跳出switch不執行。
Default要寫在所有case最後。Break可以寫可以不寫。
語法解釋:圓括號內的值會求出一個確定的值,然後從上往下匹配每個case,如果case後面的值和待檢測的值相同,匹配成功執行相應的結構體。遇見break直接跳出語句。
注意:switch語句是全等於“===”匹配,除了匹配值,還要匹配型別
var xingzuo = prompt("請輸入你的星座"); switch(xingzuo){ case "白羊座" : alert("今天要注意調整自己的狀態,有些人的睡眠質量比較差"); break; case "金牛座" : alert("今天會在感情方面遇到一些小小的問題"); break; case "雙子座" : alert("要做好心理準備會在工作上被他人挑剔找茬,這是你避免不了的事情"); break; case "巨蟹座": alert("工作上要打醒十二分精神,要不然很大可能會經常要返工哦"); break; case "獅子座": alert("戀愛中的人今天的心有點搖擺不定,有人可能會有精神上的出軌"); break; default : alert("對不起,我們沒有收錄你的星座運勢!"); break; }
switch case語句的哲學什麼?存在的意義是什麼,簡化了if else...的書寫。
會發現,下面的if語句分支中,都在判斷xingzuo是不是和某個字串相等,顯示冗餘。
所以,這種要將變數依次和不同的值比較,區分的情況,用switch case 更好。
if(xingzuo == "白羊座"){ alert("今天工作運不錯,如果工作量不大,完成工作的時候..."); }else if(xingzuo == "金牛座"){ alert("今天適合一個人靜靜地,獨處的時候能讓你想通不少..."); }else if(xingzuo == "巨蟹座"){ alert("投資容易發生虧損,容易走入誤區,要冷靜分析投資..."); }else if(xingzuo == "獅子座"){ alert("今天工作上壓力減少,做事更加輕鬆了,但工作任務..."); }else if(xingzuo == "水瓶座"){ alert("今天工作上壓力減少,做事更加輕鬆了,但工作任務..."); }else{ alert("對不起,我們沒有收錄您的星座!"); }
經過測試,發現switch進行相等判斷,底層原理是===的比較,資料型別也要比較。
var a = "5"; switch(a){ case 5: alert("哈哈"); //不會彈出!!因為資料型別不一樣 break; }
如果不寫break,那麼switch表示的非常有意思,除了執行這個case裡面的程式碼,還將無條件的執行下面的case語句,直到遇見一個break攔住它。
var a = 5; switch(a){ case 4: alert("我是4"); //沒有通過驗證,不執行 case 5: alert("我是5"); //匹配成功,彈出,但是沒有break終止,繼續往下執行 case 6: alert("我是6"); //無視這行case,直接執行case裡面的語句 break; //遇見break終止switch語句 case 7: alert("我是7"); default: alert("我是預設"); }
break:模擬跳樓現象,只走一個分支,可以善用break不寫的情況,製作特殊案例。
//使用者輸入月份,然後判斷這個月份有多少天:有30、31、28、29天 var month = parseInt(prompt("請輸入月份")); switch(month){ case 1: case 3: case 5: case 7: case 8: case 10: case 12: alert("這個月有31天"); break; case 4: case 6: case 9: case 11: alert("這個月有30天"); break; case 2: alert("這個月一般來說是28天,可能是29天!"); }
初學者最可愛的錯誤:
var month = parseInt(prompt("請輸入月份")); switch(month){ case alert("這個月有31天"); break; case alert("這個月有30天"); break; default: alert("這個月一般來說是28天,可能是29天!"); } |
這樣寫不行,因為這種叫做表示式,遇見表示式,就會計算求值。
1 || 3 || 5 || 7 || 8 || 10 || 12 |
表示式的值是1,就等價於case 1:
4 || 6 || 9 || 11: |
表示式的值是1,就等價於case 4:
switch語句,就只能幹這種事情,就是把一個值,看情況得幾,執行不同的事情。
如果要在某一個範圍內,做某件事情也行,不過不建議這樣寫,此時應該用if...else
var score = parseInt(prompt("請輸入成績")); switch(true){ case 59 < 60 : alert("不及格"); break; case score < 70 : alert("及格"); break; case score < 80 : alert("良好"); break; case score <= 100 : alert("優秀"); break; default: alert("您輸入的成績有誤!"); }
1.3三元運算子
? :是一組運算子,這是JS唯一一個需要三個元素參與的運算子。
條件 ? val1 : val2 |
表示式的值,要看條件是true還是false。
如果條件是true,那麼表示式的值就是val1。
如果條件是false,那麼表示式的值就是val2。
簡單的例子:
console.log(true ? 3 : 8); //3 console.log(false ? 3 : 8); //8 |
三元運算子,經常用這麼使用:
員工的年終獎倍數,根月薪有關,月薪大於8000,倍數就是1.2,否則是1
xishu = salary > 8000 ? 1.2 : 1; |
等價於:
if(salary > 8000){ xishu = 1.2; }else{ xishu = 1; } |
現在總結一下,條件分支的語句一共有3種,但是&& ||短路寫法也有一種選擇的感覺,總共算4種。
if……else if…… (必須立即想到!這個東西無敵)
Switch case (某方面很擅長,體現在了程式碼的清晰度上)
三元運算子(賦值的時候,根據條件有兩個可能的值,馬上想到三元運算子)
&&短路寫法(經驗問題,用的不熟悉沒事)
二、迴圈語句
JS中流程控制的語句,就兩個:條件分支、迴圈語句。靠這兩種語句,就能完成所有的程式。
迴圈語句是一系列反覆執行,直到符合特定條件的命令。
迴圈語句能夠解決大量的類似語句書寫。
另外,可以在迴圈語句中使用break和continue 語句。
迴圈語句:程式碼會反覆執行一部分語句,直到判斷條件為假時,跳出迴圈。
2.1 for迴圈語法
語法:
for(){
} |
正統語法:
for(變數初始值;迴圈的條件;增量或減量){ 迴圈體,反覆執行的程式碼 } |
for(var i = 0;i <= 100;i++){ console.log("第"+ i + "次,說你好!"); } |
變數i我們稱為迴圈變數,這個變數可以任意設定,我們習慣用i來表示迴圈變數。
for迴圈:for迴圈就是一個殼子,能幫我們反覆執行同一段程式碼,而且根據變數i依次的變化,每次執行的結果都不同。
語法上,最容易錯誤的:
for(var i = 0;i <= 100;i++;){ → 這裡不能加分號 console.log("第"+ i + "次,說你好!"); } |
for迴圈的本質,必須搞清楚:
系統遇見for迴圈結構,會立即執行語句①,此時宣告瞭一個變數i,賦值為0
系統會立即檢測,是否滿足條件②這個表示式,如果是真,則執行③;如果②是假,則跳出迴圈,for迴圈結束。
執行完③,會立即執行語句④,然後再次檢測語句②,如果為真,則執行③;如果為假,則跳出迴圈。
執行完③,會立即執行語句④,然後再次檢測語句②,如果為真,則執行③;如果為假,則跳出迴圈。
執行完③,會立即執行語句④,然後再次檢測語句②,如果為真,則執行③;如果為假,則跳出迴圈。
...直到條件②為假,整個迴圈結束。
for迴圈是一種前測試迴圈語句,在執行重複程式碼之前,必須先測試入口條件,只有條件為真,才能繼續執行。如果為假,跳出迴圈不執行。
2.2 for迴圈例子
for迴圈的本質,決定了一個事情,就是你能否預測迴圈的結果。用20道題目練習這個知識點。
①步長
for(var i = 3 ; i < 11 ; i+=4){ console.log(i); } |
②結束的符號,可以是<=
for(var i = 4 ; i <= 16 ; i+=4){ console.log(i); } |
③不一定是<或者<=
for(var i = 4 ; i != 10 ; i+=2){ console.log(i); } |
④第一次也會進行一下i<4的判定
for(var i = 6 ; i < 4 ; i++){ console.log(i); } |
(啥都沒有)
系統遇見了for迴圈,會執行語句var i = 6; ,立即進行一次i<4的判斷,結果是假。所以,一次也不執行裡面的語句,直接退出迴圈。
⑤死迴圈,別亂試:
for(var i = 1 ; i > 0 ; i++){ console.log(i); } |
⑥
for(var i = 2 ; i < 12 ; i+=3){ i += 4; console.log(i); } |
⑦
for(var i = 1 ; i < 10 ; i++){ //裡面沒有語句 } console.log(i); |
⑧
for(var i = 2 ; i < 30 ; i++){ if(i % 5 == 0){ console.log(i); } } |
⑨尋找1~100以內所有能被5或者能被6整除的數字
for(var i = 1 ; i <= 100; i++){ if(i % 5 == 0 || i % 6 == 0){ console.log(i); } } |
⑩
for(var i = 2 ; i <= 26 ; i++){ if(i % 2 == 0){ i += 3; }else{ i += 2; } console.log(i); } |
⑪
for(var i = 15 ; i > 2 ; i-=3){ console.log(i); } |
⑫
//死迴圈 for(var i = 15 ; i < 20 ; i-=3){ console.log(i); } |
⑬當迴圈變數已經在外部定義了,並不需要在①號位上重新定義,寫一個空的;
var i = 8; for(; i<12;i++){ console.log(i); } |
⑭
for(var m = 1 , n = 2 ; m + n < 12 ; m++){ n++; console.log(m); } |
⑮
var i =1; for(alert("你好");i<5;i++){ console.log(i); } |
先彈出“你好”,然後輸出:
⑯
for(var i = 1 ; i< 5 ; alert("你好")){ i++; console.log(i); } |
並且每次彈出“你好”
⑰
for(var i = 0 ; true ; alert("我第" + i + "次說我愛你")){ i++; } |
⑱
for(var i = 1 ; i < 10 ; i++){ for(var j = 1 ; j < 10 ; j++){ console.log(i + "乘" + j + "等於" + (i * j)); } } |
2.3窮舉法思想
for迴圈還沒講完,for裡面還有continue、break兩個關鍵字。
初學者最關鍵的,就是掌握for迴圈的窮舉思想。
窮舉:窮盡、完全、全部。
具體方法:
外層:用for迴圈一一列舉所有可能性
內層:用if語句進行判斷,如果滿足條件就輸出,不滿足的跳出下一次迴圈-判斷
舉例:輸出一個數的所有約數
約數:a % b == 0,沒有餘數,能整除。那麼稱a是b的倍數,稱b是a的約數(因數)。
以6為例:從1進行測試,測試到6結束。
注意:一個數的約數必然包括1及其本身。
1是6的約數,輸出 2是6的約數,輸出 3是6的約數,輸出 4不是是6的約數,直接跳出迴圈看下一個 6不是是6的約數,直接跳出迴圈看下一個 6是6的約數,輸出 |
計算機笨笨的,不能立即告訴你6能整除哪些數,所以,我們要讓計算機從1開始,一個一個驗證。
//for迴圈列舉所有可能性 for(var i = 1; i <= 6;i++){ // if判斷約數 if(6 % i == 0){ console.log(i); } }
抽象為通用的程式:
//在控制檯輸出所有的約數可能的情況 var a = parseInt(prompt('請輸入一個正整數')); for(var i = 1; i <= a;i++){ if(a % i == 0){ console.log(i + "是"+ a +"約數"); } }
把所有的可能性一一列出,然後用判斷來篩選。舉就是列舉的意思。中文比較文縐縐,窮舉法。
2.4累加器和累乘器
2.4.1累加器
累加器本質就是一個變數,用來儲存之前加的所有數之和
案例:求1~100之和
累加器進行累加,累加過程中將所有資料加進來。
var sum = 0;//定義累加器變數,必須定義初始值為0,0加任意數都等於原數本身 //迴圈累加 for(var i = 1;i <= 100;i++){ sum+=i; //sum = sum + i; } //迴圈結束後才輸出 console.log(sum);//5050
注意事項:
①累加器必須定義在迴圈之外,必須定義初始值為0,
②累加過程在for迴圈結束後才終止,如果想得到最終累加值,必須在for迴圈結構外使用。
2.4.2累乘器
累積的是一些數學的乘積。
計算6!
var sum = 1;//定義累乘器變數,必須定義初始值為1 //迴圈累乘 for(var i = 6;i >= 1;i--){ sum*=i; //sum = sum * i; } //迴圈結束後才輸出 console.log(sum);
例如:求7! = 7 * 6 * 5 * 4 * 3 * 2 * 1
var n = parseInt(prompt("請輸入一個數字")); var sum = 1;//定義累乘器變數,必須定義初始值為1 //迴圈累乘 for(var i = n;i >= 1;i--){ sum*=i; //sum = sum * i; } //迴圈結束後才輸出 console.log(sum);
注意:
1、累乘器必須定義在迴圈體外,否則變數的值會被重置清空
2、累乘器初始值必須是1,才不會影響最終結果。
三、深入學習迴圈語句
3.1 for迴圈break和continue關鍵字
哇,我已經找到我要的答案了,我不需要進行更多的迴圈了!
使用 break 語句來終止迴圈。
3.1.1 break關鍵字
作用:在條件分支和流程控制語句中,如果遇見break語句,立即中斷整個程式,不再往下執行。
比如:尋找第一個能被5整除的數:
for(var i = 1 ; i <= 100; i++){ console.log(i); if(i == 5){ break; //找到了一個5,遇見break,就立即終止迴圈 } }
break語句只能跳出當前所在最內層迴圈:
for(var i = 1; i <= 10;i++){ for(var j = 1; j <= 10;j++){ console.log(i,j); if(j == 5){ break; //只能中斷內層的迴圈,外層迴圈還在繼續 } } }
如果你這個break想終止所有迴圈,那麼JS允許你給迴圈語句加label(標籤)。在記憶體迴圈的break的後面新增外層迴圈的標籤名,就可以終止外層迴圈。
//break只能終止內層迴圈,但是我們就是想要終止外層迴圈,那麼可以給外層迴圈起名字。 waiceng:for(var i = 1;i <= 10;i++){ for(var j = 1; j <= 10;j++){ console.log(i,j); if(j == 5){ break waiceng; //可以中斷外層的waiceng的for迴圈 } } }
3.1.2 continue關鍵字
continue是繼續的意思。作用:打斷這一次的迴圈,立即進入下一次迴圈。
呃,這個答案不是我想要的,趕緊試試下一個數字吧!
遇見continue遇見,for迴圈會立即執行後面的語句,然後進入下一次迴圈。
for(var i = 1; i <= 10;i++){ if(i == 5){ continue; //當i為5時,立即重點執行後面的console語句,進入下一次迴圈 } console.log(i); }
同樣,continue只能中斷當前內層迴圈,要中斷外層迴圈加label(標籤名)
for(var i = 1; i <= 10;i++){ for(var j = 1; j <= 10;j++){ if(j == 5){ continue; //只能中斷內層的迴圈,外層迴圈還在繼續 } console.log(i,j); } }
waiceng:for(var i = 1; i <= 10;i++){ for(var j = 1; j <= 10;j++){ if(j == 5){ continue waiceng; //只能中斷內層的迴圈,外層迴圈還在繼續 } console.log(i,j); } }
3.1.3 break和continue優化程式碼
break和continue的目的,就是優化程式碼效能,優化演算法,提高運算效率。
尋找質數的方法:
waiceng:for(var i = 2; i <= 100;i++){ //要測試i是不是質數,之前的演算法是測試i的約數個數(不包括1和自己) //測試約數個數如果為0,那麼就是質數 //憑什麼我要測試約數個數?只要你有約數,你就不是質數!!! for(var j = 2;j < i;j++){ if(i % j == 0){ continue waiceng; //如果這數字被某個數字整除了,立即放棄它開始驗證下一個i。 } } console.log(i); //如果一個數字有約數,就會執行continue,就遇不見這個語句。 }
更優化的做法,可以給i開平方,少算一倍:
waiceng:for(var i = 2; i <= 100;i++){ for(var j = 2;j <= Math.sqrt(i);j++){ if(i % j == 0){ continue waiceng; } } console.log(i); }
continue簡化輸出1-10000之間的質數:
//從1~10000開始列舉,一個一個檢測是不是質數 waiceng:for(var i = 2; i <= 10000;i++){ //每次進來的i都要判斷是否是質數,不是就跳出測試下一個 //判斷這個i是不是質數,需要看看這個i的約數個數 //迴圈查詢除了1和本身之外是否有其他的約數,如果有就直接停止這一次 //進行下一次下一個數的判斷 for(var j = 2;j < i;j++){ if(i % j == 0){ //如果進入到這個位置,說明有多餘的餘數 //肯定不是質數,直接停止外層這一次所有的迴圈,進入外層下一次迴圈 continue waiceng; } } //如果能進行到這個位置,說明從沒遇見到continue //相等於除了1和本身就沒有其他約數,這個i就是質數 console.log(i); }
Break簡化,判斷質數:
var n = parseInt(prompt("請輸入一個正整數")); // 判斷是否是質數,只有兩個約數 var sum = 0; //累加器累加個數 //迴圈累加約數個數,可以縮小列舉範圍,只要2到n的開方之間有任意的約數,肯定就不是質數 //如果不是質數,立即停止迴圈 for(var i = 2 ; i < n; i++){ if(n % i == 0){ sum++; //只要有約數就加1 break; //能進入到裡面前提,在1和本身之間出現了其他約數,不是質數,別找了 } } // 迴圈結束後,sum記憶體的是n的約數個數,判斷是否等於0 if(sum == 0){ alert("是質數"); }else{ alert("不是質數"); }
更優化的做法:開平方
var n = parseInt(prompt("請輸入一個正整數")); var sum = 0; for(var i = 2 ; i <= Math.sqrt(n) ; i++){ if(n % i == 0){ sum++; break; } } if(sum == 0){ alert("是質數"); }else{ alert("不是質數"); }
3.2 do while語句
do while迴圈是一種後測試迴圈語句。先執行一次結構體,然後再判斷入口條件,如果為真可以執行下一次,如果為假跳出迴圈。也是反覆執行某一段程式碼,直到測試條件為假。
語法:
do{ ①語句 }while(②條件表示式); |
程式一開始就會執行一次①,然後驗證②是否為真,如果是真,繼續執行①……
var i = 1; do{ console.log(i); i++; }while(i <= 100);
do就是做,while就是當。
注意:如果有變數參與迴圈體,一定要注意書寫位置,如果寫在結構體內,每次進入結構體都會被重置。變數定義時需要定義在迴圈外面。
變數自加或自減的過程,需要寫在迴圈體之內,而且過程在輸出語句前和語句後得到的結果是不一樣的
這是一根後置驗證語句,怎麼著都會執行一次:
do{ console.log("哈哈"); }while(false); |
死迴圈,驗證條件橫為true:
do{ alert("哈哈"); alert("呵呵"); alert("嘻嘻"); }while(true);
for迴圈是主力語句,也就是說,for做不到的,do...while也同樣做不到。do...while能做到的,for也一定可以做到。
do...while語句沒有迴圈變數適合沒有迴圈變數的情況,經常的,它是個死迴圈。
do{ var a = prompt("你到底愛不愛我嗎?"); if(a == "愛"){ alert("但是我不愛你!"); break; //遇見break,終止迴圈 }else{ alert("回答錯誤,請重新輸入!"); } }while(true);
3.3 while語句
while語句是一個前置驗證語句,其餘的和do while一樣的。
輸出1~100;同樣也可以沒有補償,自己維護一個迴圈變數:
var n = 1; while(n <= 100){ console.log(n); n++; }
while語句是一個前置驗證語句:
while(false){ console.log("哈哈"); } |
不輸出,因為while是先驗證條件表示式,為真,然後執行裡面的語句。
同樣,while不好用,因為沒有迴圈變,所以也是基礎做死迴圈。
總結一下,JS中迴圈語句:
for(){
} |
do{
}while(); |
while() |