xia的小窩

一起來coding和碼字吧

0%

js-控制流程

大家應該都看過所謂的流程圖,每個語言都有自己的作法,接下來我們就一一探討所謂的流程。

條件式

也就是所謂的 if / else ifelse

1
2
3
4
5
6
7
8
9
10
let x = 5;
if (x == 5){
console.log(`true`);
}
else{
x = 3;
y = 8;
console.log(`${y} is not ${x}`);
}
// true

這是一個很簡單的條件式,那如果我們再加上 else if

1
2
3
4
5
6
// ...
else if {
x = 10;
// ...
}
// ...

至於 switch 跟 case.....

1
2
3
4
5
6
7
8
9
10
11
12
13
let test = "test";
switch(test) {
case "tet":
console.log("test -- 1");
break;
case "break":
console.log("break");
break;
default:
console.log("unknown");
break;
}
// unknown

其實由上面的小程式就能看出來怎麼使用了,至於 default 則是在沒有東西能跟它匹配的情況下才會使用到~~

迴圈

先介紹while家族

while 迴圈

while 的情況比較像是 在某條件成立的情況下,都會重複執行這段程式碼

1
2
while (expression):
statement

基本上很多時候都會使用到這種迴圈,來看看例子

1
2
3
4
5
6
7
8
9
10
11
12
13
let a = 10;
while (a > 5) {
if (a == 5){
break;
}
a--;
console.log(a);
}
// 9
// 8
// 7
// 6
// 5

do - while 迴圈

跟 while 差不多

1
2
3
4
5
6
7
let a = 9;
do {
if (true){
console.log(a);
a--;
}
}while (a != 10)

該迴圈至少會執行一次

for迴圈

1
2
3
for ( 初始化 ; 測試 ; 更新){
statement
}

基本上,for迴圈有一個自己的 counter,我們可以寫出來看看

1
2
3
4
for (let i = 0; i < 10; i++){
console.log(i)
}
// 0 ~ 9

for - of 迴圈

在 ES6 定義了一種新的迴圈,這種迴圈要跟可迭代的物件並用,看看下面的例子

1
2
3
4
5
6
7
let a = [1, 2, 3, 4, 5];
let sum = 0;
for (let element of a) {
sum += element
}
console.log(sum)
// 15

陣列是即時 ( live ) 迭代的,迭代過程中所做的變更可能會影響結果。

這裡提一下物件。
物件並不是不可迭代的,我們可以舉例

1
2
3
4
5
6
7
let a = { o : 'a' , c : 'c' };
for (let element of a) {
console.log(element);
}
// for (let element of a) {
// ^
//TypeError: a is not iterable

上面的程式告訴我們它不是一個可迭代的物件,如果你不想要這麼麻煩可以改成 ( for / in ) 形式,如果我們要使用上述迴圈,則必須使用 Object.keys()

1
2
3
4
5
6
let a = { o : 'a' , c : 'c' };
for (let element of Object.keys(a)) {
console.log(element);
}
// o
// c

有 keys 就有 values

1
2
3
4
5
6
let a = { o : 'a' , c : 'c' };
for (let element of Object.values(a)) {
console.log(element);
}
// a
// c

如果是兩個呢?

1
2
3
4
5
6
let a = { o : 'a' , c : 'c' };
for (let [element, value] of Object.entries(a)) {
console.log(element, value);
}
// o a
// c c

那,字串呢?

1
2
3
4
5
6
7
8
9
10
11
12
let a = {}; 
for (let alp of "mission"){
if (a[alp]){
a[alp]++;
}
else{
a[alp] = 1
}
}

console.log(a)
// { m: 1, i: 2, s: 2, o: 1, n: 1 }

字串是可以逐字元迭代的

與集合和映射,ES6 的 集合 ( set ) 跟 映射 ( map ) 都是可以迭代的,我們直接舉例

1
2
3
4
5
6
7
8
let a = "a a a b b c c d d e f";
let word = new Set(a.split(" "));
let ans = [];
for (let element of word){
ans.push(element);
}
console.log(ans);
// [ 'a', 'b', 'c', 'd', 'e', 'f' ]

Map 是一個很有趣的例子,因為 map 的迭代器不會迭代 鍵值 或 值,而是r鍵值對 ( key/ value ) ,我們來看一下

1
2
3
4
5
6
7
8
9
let a = new Map([
[1, 5], [5, 10]
]);

for (let [key, val] of a) {
console.log(key, val);
}
// 1 5
// 5 10

跟 await 組合的非同步迭代,ES2018 引進了新的一種迭代器,非同步迭代器,以及 for / of 迴圈的一種變體,稱為 for / aawait 迴圈,能與非同步迭代器並用

1
2
3
4
5
6
async function printStream(stream){
for await (let chunk of stream){
console.log(chunk);
}
}
// ....

跳躍 (jump)

這裡先從break介紹起。

break

當我們的迴圈想要停止的時候可以使用

1
2
3
4
5
for (let i = 0; i < 10; i++){
if (i == 3){
break;
}
}

continue

如其名,繼續的意思,直接看程式碼

1
2
3
4
5
6
7
8
let data = [1, 2, 3, 4, 5, 6, 7, 8]
let total = 0;
for (let i = 0; i < data.length; i++) {
if(!data[i]) continue;
total += data[i]
}
console.log(total);
// 36

return

回傳專用

1
2
3
4
5
function test(x){
return x * x
}

console.log(test(x));

yield

痾….其實語法很簡單,就是在前面加個 * ,屬於生產器函式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function *enumerate(arr) { 
for (i in arr){
yield [i, arr[i]]
}
}

let arr = ['cat', 'dog', 'pet'];
for (let [i, element] of enumerate(arr)) {
console.log(i, element);
}

// 0 cat
// 1 dog
// 2 pet

當初我在看這部份時,有參考某篇文章,點我

throw

拋出,遇到例外時可使用

1
2
3
4
5
6
7
8
9
10
11
12
13
function f(nums){
if (nums < 0){
throw new Error("nums ! < 0");
}
let a;
for (a = 0; a < 10; a++)
return a;
}

f(-4)
// throw new Error("nums ! < 0");
// ^
// Error: nums ! < 0

如果有例外被擲出,編譯器則會馬上停止正常執行程序。

try / catch / finally

如果有學過其他語言的都應該知道這是甚麼

1
2
3
4
5
6
7
8
9
try{
//正常來說這個區塊的程式碼會從上執行到下,但有時候可能會拋出一個例外(throw)
}
catch(e){
// 拋出例外時執行,但有可能因為 try 裡面的 throw 而略過
}
finally{
// 如果前2者都沒執行,則執行此區塊
}