var A = 1;
var B = 2;
var C = 2;
var D = '1';
var check1 = A == B;
var check2 = B == C;
var check3 = A != C;
var check4 = B != C;
var check5 = A == D;
console.log(check1);
console.log(check2);
console.log(check3);
console.log(check4);
console.log(check5);
https://www.jb51.net/article/93426.htm(依照此文章說明修改!=與!==用法)
這邊來進行一個白話文解析的動作
首先我們先宣告 A
、B
、C
及 D
四個變數,讓他們分別 var A = 1;
、var B = 2;
、var C = 2;
及var D = '1'
,然後我們再宣告五個變數 check1
、check2
、check3
、check4
及 check5
。
A == B;
的意思是說,請問 A 的運算元是否等於 B 的運算元,由於 A 是 1 而 B 是 2,所以 A、B 等於這件事情不正確,所以會得到一個 false
。
B == C;
的意思是說,請問 B 的運算元是否等於 C 的運算元,由於 B 是 2 而 C 也是 2,所以 B、C 相等這件事情正確,所以會得到一個 true
。
A != C;
的意思是說,請問 A 的運算元是否不等於 C,由於 A 是 1 而 C 是 2,所以 A、C 不等於這件事情正確,所以會得到一個 true
。
B != C;
的意思是說,請問 B 的運算元是否不等於 C,由於 B 是 2 而 C 也是 2,所以 B、C 不等於這件事情不正確,所以會得到一個 false
。
A == D
的意思是說,請問 A 的運算元是否等於 D 的運算元,由於 A 是 1 而 D 也是 1,雖然 A 是數字,D 是字串,他們的型別不同,但是他們的運算元仍是相同的,所以 A、D 等於這件事情正確,所以會得到一個 true
。
===
與 !==
除了運算元以外還包含型別一起比較
===
嚴格等於,運算元及型別皆須相等則回傳 true
,否則有一任何不相等則回傳 false
!==
嚴格不等於
會回傳 true
的條件有下面這三個:
a. 運算元不相等,型別相等,舉例 '1' !== '2'
b. 運算元不相等,型別不相等,舉例 1 !== '2'
c. 運算元相等,型別不相等,舉例 1 !== '1'
會回傳 false
的條件只有下面這一個:
d.運算元相等,型別相等,舉例 1 !== 1
var A = 1;
var B = '1';
var C = 2;
var D = '2';
var check1 = A === B;
var check2 = C === D;
var check3 = A !== C;
var check4 = B !== D;
var check5 = A !== D;
var check6 = B !== C;
console.log(check1);
console.log(check2);
console.log(check3);
console.log(check4);
console.log(check5);
console.log(check6);
這邊我們仍來進行一個白話文解析的動作
首先我們先宣告 A
、B
、C
及 D
四個變數,讓他們分別 var A = 1;
、var B = '1';
、var C = 2;
及var D = '2'
,然後我們再宣告六個變數 check1
、check2
、check3
、check4
、check5
及 check6
。
A === B;
的意思是說,請問 A 的運算元與型別是否皆等於 B 的運算元與型別,由於 A 是 1
的數字而 B 是 '1'
的字串,所以 A、B 嚴格等於這件事情不正確,所以會得到一個 false
。
C === D;
的意思是說,請問 C 的運算元與型別是否皆等於 D 的運算元與型別,由於 C 是 2
的數字而 D 是 '2'
的字串,所以 C、D 嚴格等於這件事情不正確,所以會得到一個 false
。
A !== C;
的意思是說,請問 A 的運算元與型別是否有任一不等於 C 的運算元與型別,由於 A 是 1
的數字而 C 是 2
的數字,符合條件 運算元不相等,型別相等,A、C 嚴格不等於這件事情正確,所以會得到一個 true
。
B !== D;
的意思是說,請問 B 的運算元與型別是否有任一不等於 D 的運算元與型別,由於 B 是 '1'
的字串而 D 是 '2'
的字串,符合條件 運算元不相等,型別相等,B、D 嚴格不等於這件事情正確,所以會得到一個 true
。
A !== D;
的意思是說,請問 A 的運算元與型別是否有任一不等於 D 的運算元與型別,由於 A 是 1
的數字而 D 是 '2'
的字串,符合條件 運算元不相等,型別不相等,A、D 嚴格不等於這件事情正確,所以會得到一個 true
。
B !== C;
的意思是說,請問 B 的運算元與型別是否有任一不等於 C 的運算元與型別,由於 B 是 '1'
的字串而 C 是 2
的數字,符合條件 運算元不相等,型別不相等,B、C 嚴格不等於這件事情正確,所以會得到一個 true
。
>
與 <
還有 >=
與 <=
這個很簡單,就是 大於 和 小於 以及 大於等於 還有 小於等於,沒啥特別的,下面的範例程式碼應該也很好理解,就不再做多餘的解釋了。
var A = 30;
var B = 30;
var C = 50;
var D = 60;
var check1 = A > B;
var check2 = A >= B;
var check3 = C < B;
var check4 = C < D;
console.log(check1);
console.log(check2);
console.log(check3);
console.log(check4);
邏輯運算子
&&
這個叫做 AND 的意思
用法是這樣的,重點在於條件必須同時成立。
var A = 30;
var B = 30;
var C = 50;
var D = 60;
var check1 = C > B && C < D;
var check2 = B >= A && B < C;
var check3 = D > C && A > B;
var check4 = A <= B && A > D;
console.log(check1);
console.log(check2);
console.log(check3);
console.log(check4);
這裡我們仍來進行一個白話文解析的動作
首先我們先宣告 A
、B
、C
和 D
四個變數,讓他們分別 var A = 30;
、var B = 30;
、var C = 50;
還有 var D = 60;
,然後我們再宣告四個變數 check1
、check2
、check3
、check4
。
C > B && C < D
的意思是說,請問 C = 50
是否大於 B = 30
而且 C = 50
是否小於 D = 60
,經比較後,這兩件事情皆成立,所以會得到一個 true
。
B >= A && B < C
的意思是說,請問 B = 30
是否大於等於 A = 30
而且 B = 30
是否小於 C = 50
,經比較後,這兩件事情皆成立,所以會得到一個 true
。
D > C && A > B
的意思是說,請問 D = 60
是否大於 C = 50
而且 A = 30
是否大於 B = 30
,經比較後,這兩件事情僅 D > C
成立,所以會得到一個 false
。
A <= B && A > D
的意思是說,請問 A = 30
是否小於等於 B = 30
而且 A = 30
是否大於 D = 60
,經比較後,這兩件事情僅 A <= B
成立,所以會得到一個 false
。
||
這個叫做 OR 的意思
用法是這樣的,重點在於條件擇一成立即可。
var A = 30;
var B = 30;
var C = 50;
var D = 60;
var check1 = C > B || C < D;
var check2 = B >= A || B < C;
var check3 = D > C || A > B;
var check4 = A <= B || A > D;
console.log(check1);
console.log(check2);
console.log(check3);
console.log(check4);
所以我們用相同的範例再來解釋一次,當我們把 &&
都改成 ||
後,原本條件僅有一個成立的 check3
及 check4
都從 false
變成了 true
了。
!
這個叫做 NOT 的意思
用於反轉傳回的值,本來是 true
會變成 false
,本來是 false
會變成 true
。
var A = 1;
var B = '1';
check1 = !(A == B);
console.log(check1);
check2 = !(A === B);
console.log(check2);
之前在介紹 ===
有用過了這個例子,現在我們加上了 !
以後,本來是 true
的變成了 false
,本來是 false
的就變成了 true
了。
if 條件式
終於我們要來正式介紹 if 條件式了,if 條件式未來會廣泛的運用在各個地方,用來進行很多條件的判斷。
if 寫法
var weather = '太陽';
if (weather == '太陽'){
console.log('今天晴空萬里');
}else{
console.log('今天天氣不是很好');
首先我們先 var weather = '太陽';
,再來開始我們的 if
,後面接著就是比較的條件,我們的條件是 (weather == '太陽')
,若比較出來是 true
,就執行後面 {}
內的程式 console.log('今天晴空萬里')
,後接一個 else{console.log('今天天氣不是很好');}
的意思是說,如果前面的條件比較得到 false
,那就執行這個 console.log('今天天氣不是很好');
。
else if 寫法,多條件比較
var temp = 28;
function weather(clothes){
console.log('我今天想穿' + clothes);
if (temp <= 20){
weather('羽絨衣毛褲');
}else if (temp <= 30 && temp > 20){
weather('短T恤長褲');
}else if (temp > 30){
weather('短褲短袖');
}else{
console.log('我不知道要穿什麼,怎麼辦呢?')
首先,var temp = 28;
,然後再寫一個 function weather(clothes)
,等後面的 if
比較出條件後回過來執行這個 function
,再來就是 if
,後面比較的條件是 (temp <= 20)
,若是 true
,就執行 weather('羽絨衣毛褲');
,若是 false
,就繼續後接的 else if
,繼續下一個比較條件 (temp <= 30 && temp > 20)
,若是 true
,就執行 weather('短T恤長褲');
,若是 false
,就繼續後接的 else if
,繼續下一個比較條件 (temp > 30)
,若是 true
,就執行 weather('短褲短袖');
,若是 false
,就執行最後接的else{console.log('我不知道要穿什麼,怎麼辦呢?')}
,意思就是前面的筆記條件全部都是 false
的話,就執行 console.log('我不知道要穿什麼,怎麼辦呢?')
。
switch 寫法
這是啥?怎麼跑來了一個和 if
不相干的東西呢?switch
是一個和 if
有類似功能的語法,但與 if
不一樣的是,if
的小括弧 ()
內條件若成立,才會跑後面大括弧 {}
內的程式,而 switch
僅有 case
成立時,才會跑後面的 function
,然後因為後面接了一個 break
,所以程式就會在這邊跳出,反觀 if
則會全部跑完,所以在編譯的速度上來說,switch
比較不耗資源。
這個就是使用 switch
寫法
var weather = '下雨';
var clothes = ['遮陽帽', '薄外套', '雨傘'];
function putonClothes (fitting){
console.log('今天要帶' + fitting);
switch (weather){
case '太陽': putonClothes (clothes[0]);
break;
case '陰天': putonClothes (clothes[1]);
break;
case '下雨': putonClothes (clothes[2]);
break;
default: console.log ('天氣不穩定,通通都帶好了');
break;
一樣的,我們先把需要的變數 var weather
與 var clothes
宣告好,然後 function putonClothes (fitting)
也寫好,再來後面就開始我們的 switch
了,後面的 ()
內要放進去的是要比對的值,我們這邊放的是 (weather)
這個變數,接下來 {}
內就是要開始和前面的 (weather)
進行比對了,case '太陽': putonClothes (clothes[0])
,這個的意思是 weather
若等於 '太陽'
,則執行 putonClothes (clothes[0])
,後接 break
是指若比對成功,則程式就從這個地方跳出,不執行後面的 case
了,若比對不成功,則繼續往後面的 case '陰天': putonClothes (clothes[1]);
進行比對,若成功一樣就跳出,若比對不成功,就往下一個 case '下雨': putonClothes (clothes[2]);
進行比對,若成功一樣就跳出,若不成功則往後執行 default: console.log ('天氣不穩定,通通都帶好了');
,這個 default
的意思就是,前面的 case
全部都沒有比對成功,所以就執行這個 console.log ('天氣不穩定,通通都帶好了');
的意思,所以,經比對結果,Console 顯示 '今天要帶傘'
。
若改用 if
改寫來得到相同的產出呢?就變成下面這樣了,
var weather = '下雨';
var clothes = ['遮陽帽', '薄外套', '雨傘'];
function putonClothes (fitting){
console.log('今天要帶' + fitting);
if (weather == '太陽'){
putonClothes (clothes[0]);
}else if (weather == '陰天'){
putonClothes (clothes[1]);
}else if (weather == '下雨'){
putonClothes (clothes[2]);
}else{
console.log ('天氣不穩定,通通都帶好了');
所以甚麼時候用 if
,什麼時候用 switch
呢?
若是判斷的值可以計算,或是介於一個區間,可使用 大於、小於 這類運算子,簡單來說像是數字類型的,請用 if
。
若是判斷的值可以用比對的方式來看相同不相同,就像是字串一樣,那就可以用 switch
了。
以上就是今天介紹的 if
條件式,謝謝大家。
六角學院課程:JavaScript 入門篇 - 學徒的試煉
暱稱:AlecWang
Hi 大家好,我是卡斯伯。
這次要跟大家來介紹 CSS 的變數功能,在過去如果要在樣式表中使用變數功能,就會仰賴 Sass、Less 這樣的 CSS 預處理器,因為 CSS 本身是屬於靜態的樣式表,所以傳統上是沒有辦法做到這樣的特性,就只能透過編譯來達到。而現在 CSS 加入了變數功能,也因為此新功能是在原本的樣式表上做加強,所以看起來結構會有些「奇特」!?
為何樣式表需要變數呢?無論是使用 Sass 做編譯或是現在直接使用 CSS 變數有什麼好處呢?
1. 統一整個樣式表的樣式:你的紅不代表我的紅。開發的過程中一定會有許多色彩、尺寸是不斷的重複使用,因此原始碼中就可能會產生許多類似但卻不相同的數值,在管理上以及視覺的統一就會有很大的問題。
2. 基於預定的數值做計算:當有了基準數值後,變數還能基於這些值做計算,如上述的更深一點的紅、兩倍的距離等等;調整變數的同時也不需要一一的取代,這些數值都會依據變數直接套用。
以上的兩點改變,讓樣式的管理更為方便、視覺上更有統整性,自然也會加快樣式上的開發。
而 Sass 與 CSS 變數更大的不同是:Sass 編譯後終究是 CSS,而本篇會用純 CSS 來與大家分享 CSS 變數上的獨特之處,包含:混合不同單位的運算、修改 CSS 變數改變整體畫面等技法。
## 使用 CSS Variables
使用前,大家最關心的一定是支援度,一樣是 IE 不支援,其他大部分都是支援的,以下附上支援圖(2019 年 12 月 [Can I use](https://caniuse.com/#search=css%20variables))。
![images](/img/2438C6C3-F844-4386-AFC8-2EA76FB43FC3a8g3c.png)
使用 CSS 變數時也區分為兩個階段:
1. 定義變數:CSS Variables 的變數定義必須定義在 CSS 選取器內,大多數來說會建議定義在 `:root` 最高層級的選取器便於取用。
2. 取用變數值:一般來說宣告變數會使用 `var {變數名稱}` 的方式使用,但在 CSS Variables 則是需要在 **取值時** 才加入 `var (變數名稱)`。
接下來開始來撰寫 CSS Variables 吧!
記得兩個步驟,**第一個步驟是宣告變數**,我們可以將本範例中會運用到的變數都放在 `:root` 選取器內,並且使用 `--自訂名稱`作為屬性的方式來宣告變數。
```css
:root {
--primary: Aquamarine;
--background-color: Teal;
接下來來到取值的階段,取值時前方依然是撰寫我們需要套用的樣式屬性,後方再接著使用 `var (--變數名稱)` 來套用。
```css
body {
background: var(--background-color);
範例圖片:
![images](/img/貼上的影像_2019_12_7_下午7_17aeaz7.png)
範例網址:https://codepen.io/Wcc723/pen/oNgXraG
### 變數搭配 RWD!
相對於 Sass 的變數來說,CSS 的變數是可以再次改變的,且改變的方式也是依據 CSS 「後者覆蓋前者」的特性,以下就使用 “中斷點” 做為條件來使後者的樣式覆蓋前者吧。
製作響應式時,因為螢幕大小的不同通常會需要調整文字大小來符合需求,最常見的方式就是透過選取器一一覆蓋字體大小,如果透過變數的方式就可以統一切換整體文字大小,不需要一一的調整每個選取器。
```css
:root {
--font-size: 14px;
/* 使用變數定義文字大小 */
font-size: var(--font-size);
/* 除此之外,還可以透過 calc 用相同變數做運算,讓特定的文字更大獲更小 */
font-size: calc(var(--font-size) * 1.5);
接下來只要調整中斷點內的變數,上段的 `p`、`h1` 選取器就會套用新的變數值。
```css
@media (min-width: 480px) {
:root {
--font-size: 18px;
本範例可透過縮放畫面看到不同結果,建議到範例中觀看,範例網址:https://codepen.io/Wcc723/pen/JjodQVJ
### JavaScript 操作 CSS 變數
除了使用覆蓋的方式外,萬能的 JavaScript 也同樣能夠調整 CSS 變數,此方式也就幾乎跳脫所有的限制可自由運用 CSS 變數。
此範例中先預訂了一個變數 `--size`,並且給予值 200px。
```css
:root {
--size: 200px;
設定 CSS Variables 與設定一般 CSS 屬性方式是相同的,先選取 `document.documentElement.root` 就能在下方的 style 設定屬性 `{ '--變數名稱', '值' }`。
```js
const root = document.documentElement;
root.style.setProperty('--size', `${this.value}px`)
範例圖片:
![images](/img/貼上的影像_2019_12_7_下午7_18ag57v.png)
範例網址:https://codepen.io/Wcc723/pen/xxbwXZQ
### 使用不科學的 Calc 做計算
除此之外,CSS 中更有一個神奇的運算方法 `calc`,此函式可以無視讓不同單位的數值直接做運算,如百分比與絕對單位運算(ex: 100% - 30px)。CSS Variables 也同樣能夠搭配此方法產生新的值。
calc 是作為函式使用,因此可將預期運算的方法置入 `calc()` 的括號內即可。
```css
.box-1 {
width: calc(100% - var(--size));
[images](/img/貼上的影像_2019_12_7_下午7_19ah7w6.png)
本範例可以透過拖曳 range input 改變寬度的範圍,範例網址看結果:https://codepen.io/Wcc723/pen/OJPVeKd
### 計算色彩
在 CSS 色彩中除了常見的色碼外(ex: #fff),`rgb`、`hls` 也都是常見的色彩標示方式,這些色彩標示方式都是直接置入 **純數值**。因此,也可透過 `calc` 這一個神奇的運算方法來調整它。
此範例使用 rgb、calc 來繪製 CSS 漸層。
```css
/* 定義一個值 */
:root {
--c: 255;
/* 搭配不同的運算給予不同的 r, g, b */
body {
background-image: linear-gradient(
calc(var(--c) - 60),
calc(var(--c) - 40),
calc(var(--c))
calc(var(--c) - 20),
calc(var(--c) - 10),
calc(var(--c))
範例圖片:
[images](/img/貼上的影像_2019_12_7_下午7_20aimd0.png)
本範例透過調整 input range 會有白天跟黑夜的切換,範例網址看結果:https://codepen.io/Wcc723/pen/OJPyxVM
### Bootstrap
除了本文所介紹的範例外,應該也會有許多讀者會疑惑 CSS Variables 還有用在哪些地方呢?其實在最主流的 CSS 函式庫中就有包含 CSS Variables 可以運用,主要用途是讓開發者做自訂元件時可以直接取用,且不需要經過編譯。
CSS variables offer similar flexibility to Sass’s variables, but without the need for compilation before being served to the browser.
可以參考:https://getbootstrap.com/docs/4.4/getting-started/theming/#css-variables
Bootstrap 預設有提供所有的主題色彩作為變數,因此我們套用 Bootstrap 時可不需要另外撰寫色碼,直接可透過變數取得該色彩。
```css
color: var(--primary)
本範例直接取用 Bootstrap 變數,範例網址直接看:https://codepen.io/Wcc723/pen/bGNdPmZ
1. `==` 運算元 ***等於***,回傳 `true`,不等於回傳 `false`,無關型別
2. `!=` 運算元 ***不等於***,回傳 `false`,不等於回傳 `true`,無關型別
`==` 與 `!=` 是拿來做比較用的,比較什麼東西呢?比較是否一樣與不一樣,也就是是否等於和是否不等於,但是只限於運算元的值來做比較,不包含型別,那麼比較出來的值只有 Yes 或是 No 而已,但是屆時 console 卻不是顯示 Yes 或是 No,而是顯示 `true` 或是 `false`,這個叫做布林值 (Boolean),布林值就是只有 `true` 和 `false` 兩種值而已。
* 所以是怎麼個比法呢?就像下面這樣
```js=
var A = 1; // 數字 1
var B = 2; // 數字 2
var C = 2; // 數字 2
var D = '1'; // 字串 1
var check1 = A == B;
var check2 = B == C;
var check3 = A != C;
var check4 = B != C;
var check5 = A == D;
console.log(check1); // console 顯示 false
console.log(check2); // console 顯示 true
console.log(check3); // console 顯示 true
console.log(check4); // console 顯示 false
console.log(check5); // console 顯示 true
https://www.jb51.net/article/93426.htm(依照此文章說明修改!=與!==用法)
* 這邊來進行一個白話文解析的動作
首先我們先宣告 `A`、`B`、`C` 及 `D` 四個變數,讓他們分別 `var A = 1;`、`var B = 2;`、`var C = 2;`及`var D = '1'`,然後我們再宣告五個變數 `check1`、`check2`、`check3`、`check4` 及 `check5`。
`A == B;` 的意思是說,請問 A 的運算元是否等於 B 的運算元,由於 A 是 1 而 B 是 2,所以 A、B 等於這件事情不正確,所以會得到一個 `false`。
`B == C;` 的意思是說,請問 B 的運算元是否等於 C 的運算元,由於 B 是 2 而 C 也是 2,所以 B、C 相等這件事情正確,所以會得到一個 `true`。
`A != C;` 的意思是說,請問 A 的運算元是否**不**等於 C,由於 A 是 1 而 C 是 2,所以 A、C 不等於這件事情正確,所以會得到一個 `true`。
`B != C;` 的意思是說,請問 B 的運算元是否**不**等於 C,由於 B 是 2 而 C 也是 2,所以 B、C 不等於這件事情不正確,所以會得到一個 `false`。
`A == D` 的意思是說,請問 A 的運算元是否等於 D 的運算元,由於 A 是 1 而 D 也是 1,雖然 A 是數字,D 是字串,他們的型別不同,但是他們的運算元仍是相同的,所以 A、D 等於這件事情正確,所以會得到一個 `true`。
* `===` 與 `!==` 除了運算元以外還包含型別一起比較
1. `===` ***嚴格等於***,運算元及型別皆須相等則回傳 `true`,否則有一任何不相等則回傳 `false`
2. `!==` ***嚴格不等於***
會回傳 `true` 的條件有下面這三個:
a. 運算元不相等,型別相等,舉例 `'1' !== '2'`
b. 運算元不相等,型別不相等,舉例 `1 !== '2'`
c. 運算元相等,型別不相等,舉例 `1 !== '1'`
會回傳 `false` 的條件只有下面這一個:
d.運算元相等,型別相等,舉例 `1 !== 1`
```js=
var A = 1;
var B = '1';
var C = 2;
var D = '2';
var check1 = A === B;
var check2 = C === D;
var check3 = A !== C;
var check4 = B !== D;
var check5 = A !== D;
var check6 = B !== C;
console.log(check1); // console 顯示為 false
console.log(check2); // console 顯示為 false
console.log(check3); // console 顯示為 true
console.log(check4); // console 顯示為 true
console.log(check5); // console 顯示為 true
console.log(check6); // console 顯示為 true
* 這邊我們仍來進行一個白話文解析的動作
首先我們先宣告 `A`、`B`、`C` 及 `D` 四個變數,讓他們分別 `var A = 1;`、`var B = '1';`、`var C = 2;`及`var D = '2'`,然後我們再宣告六個變數 `check1`、`check2`、`check3`、`check4`、`check5` 及 `check6`。
`A === B;` 的意思是說,請問 A 的運算元與型別是否皆等於 B 的運算元與型別,由於 A 是 `1` 的數字而 B 是 `'1'` 的字串,所以 A、B 嚴格等於這件事情不正確,所以會得到一個 `false`。
`C === D;` 的意思是說,請問 C 的運算元與型別是否皆等於 D 的運算元與型別,由於 C 是 `2` 的數字而 D 是 `'2'` 的字串,所以 C、D 嚴格等於這件事情不正確,所以會得到一個 `false`。
`A !== C;` 的意思是說,請問 A 的運算元與型別是否有任一不等於 C 的運算元與型別,由於 A 是 `1` 的數字而 C 是 `2` 的數字,符合條件 ***運算元不相等,型別相等***,A、C 嚴格不等於這件事情正確,所以會得到一個 `true`。
`B !== D;` 的意思是說,請問 B 的運算元與型別是否有任一不等於 D 的運算元與型別,由於 B 是 `'1'` 的字串而 D 是 `'2'` 的字串,符合條件 ***運算元不相等,型別相等***,B、D 嚴格不等於這件事情正確,所以會得到一個 `true`。
`A !== D;` 的意思是說,請問 A 的運算元與型別是否有任一不等於 D 的運算元與型別,由於 A 是 `1` 的數字而 D 是 `'2'` 的字串,符合條件 ***運算元不相等,型別不相等***,A、D 嚴格不等於這件事情正確,所以會得到一個 `true`。
`B !== C;` 的意思是說,請問 B 的運算元與型別是否有任一不等於 C 的運算元與型別,由於 B 是 `'1'` 的字串而 C 是 `2` 的數字,符合條件 ***運算元不相等,型別不相等***,B、C 嚴格不等於這件事情正確,所以會得到一個 `true`。
* `>` 與 `<` 還有 `>=` 與 `<=`
這個很簡單,就是 ***大於*** 和 ***小於*** 以及 ***大於等於*** 還有 ***小於等於***,沒啥特別的,下面的範例程式碼應該也很好理解,就不再做多餘的解釋了。
```js=
var A = 30;
var B = 30;
var C = 50;
var D = 60;
var check1 = A > B;
var check2 = A >= B;
var check3 = C < B;
var check4 = C < D;
console.log(check1); // console 顯示 false
console.log(check2); // console 顯示 true
console.log(check3); // console 顯示 false
console.log(check4); // console 顯示 true
### 邏輯運算子
* `&&` 這個叫做 AND 的意思
用法是這樣的,重點在於條件必須同時成立。
```js=
var A = 30;
var B = 30;
var C = 50;
var D = 60;
var check1 = C > B && C < D;
var check2 = B >= A && B < C;
var check3 = D > C && A > B;
var check4 = A <= B && A > D;
console.log(check1); // console 顯示 true
console.log(check2); // console 顯示 true
console.log(check3); // console 顯示 false
console.log(check4); // console 顯示 false
* 這裡我們仍來進行一個白話文解析的動作
首先我們先宣告 `A`、`B`、`C` 和 `D` 四個變數,讓他們分別 `var A = 30;`、`var B = 30;`、`var C = 50;` 還有 `var D = 60;`,然後我們再宣告四個變數 `check1`、`check2`、`check3`、`check4`。
`C > B && C < D` 的意思是說,請問 `C = 50` 是否大於 `B = 30` 而且 `C = 50` 是否小於 `D = 60`,經比較後,這兩件事情皆成立,所以會得到一個 `true`。
`B >= A && B < C` 的意思是說,請問 `B = 30` 是否大於等於 `A = 30` 而且 `B = 30` 是否小於 `C = 50`,經比較後,這兩件事情皆成立,所以會得到一個 `true`。
`D > C && A > B` 的意思是說,請問 `D = 60` 是否大於 `C = 50` 而且 `A = 30` 是否大於 `B = 30`,經比較後,這兩件事情僅 `D > C` 成立,所以會得到一個 `false`。
`A <= B && A > D` 的意思是說,請問 `A = 30` 是否小於等於 `B = 30` 而且 `A = 30` 是否大於 `D = 60`,經比較後,這兩件事情僅 `A <= B` 成立,所以會得到一個 `false`。
* `||` 這個叫做 OR 的意思
用法是這樣的,重點在於條件擇一成立即可。
```js=
var A = 30;
var B = 30;
var C = 50;
var D = 60;
var check1 = C > B || C < D;
var check2 = B >= A || B < C;
var check3 = D > C || A > B;
var check4 = A <= B || A > D;
console.log(check1); // console 顯示 true
console.log(check2); // console 顯示 true
console.log(check3); // console 顯示 true
console.log(check4); // console 顯示 true
所以我們用相同的範例再來解釋一次,當我們把 `&&` 都改成 `||` 後,原本條件僅有一個成立的 `check3` 及 `check4` 都從 `false` 變成了 `true` 了。
* `!` 這個叫做 NOT 的意思
用於反轉傳回的值,本來是 `true` 會變成 `false`,本來是 `false` 會變成 `true`。
```js=
var A = 1;
var B = '1';
check1 = !(A == B);
console.log(check1); // console 顯示為 false
check2 = !(A === B);
console.log(check2); // console 顯示為 true
之前在介紹 `===` 有用過了這個例子,現在我們加上了 `!` 以後,本來是 `true` 的變成了 `false`,本來是 `false` 的就變成了 `true` 了。
## if 條件式
終於我們要來正式介紹 if 條件式了,if 條件式未來會廣泛的運用在各個地方,用來進行很多條件的判斷。
### if 寫法
```js=
var weather = '太陽';
if (weather == '太陽'){
console.log('今天晴空萬里');
}else{
console.log('今天天氣不是很好');
// console 顯示 '今天晴空萬里'
首先我們先 `var weather = '太陽';`,再來開始我們的 `if`,後面接著就是比較的條件,我們的條件是 `(weather == '太陽')`,若比較出來是 `true`,就執行後面 `{}` 內的程式 `console.log('今天晴空萬里')`,後接一個 `else{console.log('今天天氣不是很好');}` 的意思是說,如果前面的條件比較得到 `false`,那就執行這個 `console.log('今天天氣不是很好');`。
### else if 寫法,多條件比較
```js=
var temp = 28;
// 氣溫
function weather(clothes){
console.log('我今天想穿' + clothes);
if (temp <= 20){
weather('羽絨衣毛褲');
}else if (temp <= 30 && temp > 20){
weather('短T恤長褲');
}else if (temp > 30){
weather('短褲短袖');
}else{
console.log('我不知道要穿什麼,怎麼辦呢?')
// console 顯示 '我今天想穿短T恤長褲'
首先,`var temp = 28;`,然後再寫一個 `function weather(clothes)`,等後面的 `if` 比較出條件後回過來執行這個 `function`,再來就是 `if`,後面比較的條件是 `(temp <= 20)`,若是 `true`,就執行 `weather('羽絨衣毛褲');`,若是 `false`,就繼續後接的 `else if`,繼續下一個比較條件 `(temp <= 30 && temp > 20)`,若是 `true`,就執行 `weather('短T恤長褲');`,若是 `false`,就繼續後接的 `else if`,繼續下一個比較條件 `(temp > 30)`,若是 `true`,就執行 `weather('短褲短袖');`,若是 `false`,就執行最後接的`else{console.log('我不知道要穿什麼,怎麼辦呢?')}`,意思就是前面的筆記條件全部都是 `false` 的話,就執行 `console.log('我不知道要穿什麼,怎麼辦呢?')`。
### switch 寫法
這是啥?怎麼跑來了一個和 `if` 不相干的東西呢?`switch` 是一個和 `if` 有類似功能的語法,但與 `if` 不一樣的是,`if` 的小括弧 `()` 內條件若成立,才會跑後面大括弧 `{}` 內的程式,而 `switch` 僅有 `case` 成立時,才會跑後面的 `function`,然後因為後面接了一個 `break`,所以程式就會在這邊跳出,反觀 `if` 則會全部跑完,所以在編譯的速度上來說,`switch` 比較不耗資源。
* 這個就是使用 `switch` 寫法
```js=
var weather = '下雨';
var clothes = ['遮陽帽', '薄外套', '雨傘'];
function putonClothes (fitting){
console.log('今天要帶' + fitting);
switch (weather){
case '太陽': putonClothes (clothes[0]);
break;
case '陰天': putonClothes (clothes[1]);
break;
case '下雨': putonClothes (clothes[2]);
break;
default: console.log ('天氣不穩定,通通都帶好了');
break;
// console 顯示 今天要帶雨傘
一樣的,我們先把需要的變數 `var weather` 與 `var clothes` 宣告好,然後 `function putonClothes (fitting)` 也寫好,再來後面就開始我們的 `switch` 了,後面的 `()` 內要放進去的是要比對的值,我們這邊放的是 `(weather)` 這個變數,接下來 `{}` 內就是要開始和前面的 `(weather)` 進行比對了,`case '太陽': putonClothes (clothes[0])`,這個的意思是 `weather` 若等於 `'太陽'`,則執行 `putonClothes (clothes[0])`,後接 `break` 是指若比對成功,則程式就從這個地方跳出,不執行後面的 `case` 了,若比對不成功,則繼續往後面的 `case '陰天': putonClothes (clothes[1]);` 進行比對,若成功一樣就跳出,若比對不成功,就往下一個 `case '下雨': putonClothes (clothes[2]);`進行比對,若成功一樣就跳出,若不成功則往後執行 `default: console.log ('天氣不穩定,通通都帶好了');`,這個 `default` 的意思就是,前面的 `case` 全部都沒有比對成功,所以就執行這個 `console.log ('天氣不穩定,通通都帶好了');`的意思,所以,經比對結果,Console 顯示 ``'今天要帶傘'``。
若改用 `if` 改寫來得到相同的產出呢?就變成下面這樣了,
```js=
var weather = '下雨';
var clothes = ['遮陽帽', '薄外套', '雨傘'];
function putonClothes (fitting){
console.log('今天要帶' + fitting);
if (weather == '太陽'){
putonClothes (clothes[0]);
}else if (weather == '陰天'){
putonClothes (clothes[1]);
}else if (weather == '下雨'){
putonClothes (clothes[2]);
}else{
console.log ('天氣不穩定,通通都帶好了');
所以甚麼時候用 `if`,什麼時候用 `switch` 呢?
* 若是判斷的值可以計算,或是介於一個區間,可使用 ***大於***、***小於*** 這類運算子,簡單來說像是數字類型的,請用 `if`。
* 若是判斷的值可以用比對的方式來看相同不相同,就像是字串一樣,那就可以用 `switch` 了。
以上就是今天介紹的 `if` 條件式,謝謝大家。
## 參考資料
* 六角學院課程:JavaScript 入門篇 - 學徒的試煉
從 0 學習 JavaScript 筆記-建立 JS 環境、alert、textContent
# 為什麼要學 JavaScript
江湖中傳聞 `JavaScript` 是一個無底洞,是一個又簡單又困難的程式語言,初入前端世界的我小生怕怕,但又是現在前端應該具備的基本能力,只好放下恐懼,勇往直前了...
為了督促自己學習上有成效,也知道 `JavaScript` 是學無止盡,就自己設定一個目標,希望 30 天可以學到一個程度後,可以寫出一個有互動的網站,也期待讓這份筆記可以在未來翻閱時能幫助到自己。
## JavaScript 概述
### 一般來說,完整的JavaScript包括以下幾個部分:
* ECMAScript,描述了該語言的語法和基本物件
* 文件物件模型(DOM),描述處理網頁內容的方法和介面
* 瀏覽器物件模型(BOM),描述與瀏覽器進行互動的方法和介面
### JavaScript的基本特點如下:
* 是一種解釋性程式語言(代碼不進行預編譯)。
* 主要用來向 HTML 頁面添加互動行為。
* 可以直接嵌入 HTML 頁面,但寫成單獨的 JS 檔案有利於結構和行為的分離。
### JavaScript常用來完成以下任務:
* 嵌入動態文字於 HTML 頁面
* 對瀏覽器事件作出回應
* 讀寫 HTML 元素
* 在資料被提交到伺服器之前驗證資料
* 檢測訪客的瀏覽器資訊
* 控制 cookies,包括建立和修改等
## 正文開始
首先先學習建立一個 `JavaScript` 的環境,環境建立如下:
```html
<!DOCTYPE html>
<html lang="en">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<script src="js/all.js"></script>
</body>
</html>
通常我會把 SCSS 跟 JS 另外各自開立一個資料夾來管理,讓根目錄保持整潔。
## alert 警示語法
JS 有個警示語法 (alert) 可以來測驗一下目前寫的 JS 有無效果,滿好用的,然後是這樣寫的:
```javascript
alert('test');
記得括弧內的「文字」要使用**單引號**或**雙引號**,才能顯示正確文字。
可以玩一下 [codepen](http://https://codepen.io/hnzxewqw/full/RwwEqWx)
這個語法很常被使用,像是錯誤提示、或是購買商品成功或錯誤提示的彈跳視窗,但沒想到寫法這麼簡單。
*另外如果不喜歡原本預設的 alert 視窗,可以看這一篇 [SweetAlert 的作法](http://https://w3c.hexschool.com/blog/13ef5369)*
原則上通常會把 JS 放在結尾的 `</body>` 前面,確保都讀完「靜態的」程式碼後再執行 JS。
*<有原則當然也有例外,如果特定要執行 JS 做特別的效果,也可以把 JS 的程式碼放在 `HTML` 中>*
### textContent 的作法
要用 JS 控制網頁的文字,有一個 `textContent` 的語法,而這個語法編寫如下:
```javascript
document.getElementById('title1').textContent = 'Hello World';
白話文解釋:**網頁主體(document)**,宣告用 **使用 id 元件(getElementById)** 加上設定的 **id名稱** 將原本的文字,使用 **文字內容(textContent)** 的語法變成 **指定文字(這裡是寫 Hello World)**
不過這邊有一個地方要注意,如果把 `<script>` 標籤寫在 head 裡面的時候,會發現網頁不會有效果,反而一直停在原本的寫的畫面。然後打開 Chrome 檢查會看到 console 裡面會顯示下圖:
![images](/img/20119300NICI4FA7thy7v8y.png)
原因是網頁是從上往下閱讀,但如果發現在 head 就讀到 `<script>` 標籤時,因為找不到內容而無法順利顯示 JS ,所以常常會把 JS 寫在最後面就是這個原因。
**原本 HTML 程式碼如下:**
```html
<!DOCTYPE html>
<html lang="en">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>JavaScript practice Day1</title>
</head>
<h1 id="title1">This is Title</h1>
<script src="js/all.js"></script>
</body>
</html>
正常來說畫面應該會是下圖所示:
![images](/img/註解_2019-11-18_225433y83co.png)
可以點一下[這裡](http://https://codepen.io/hnzxewqw/pen/OJJraKe)把 JS 的註解打開,然後重新整理就會看到透過 JS 就把原本的文字:This is Title,變成:Hello World 囉~!!
文獻參考 https://zh.wikipedia.org/wiki/JavaScript#%E8%82%87%E5%A7%8B%E6%96%BC%E7%B6%B2%E6%99%AF
這邊將會使用我先前參加六角學院的甜點電商切版活動來當作本次的專案範例
專案:[GitHub](https://github.com/hsiangfeng/Pug-Sweetaste)
![Sweetaste](https://i.imgur.com/pCXIAnZ.png)
## 修改 gulpfile
起手式這邊要來稍微調整一下 gulpfile,因為我這個專案是使用 Gulp 所開發的,所以加入以下程式碼即可:
```js
// copyPWA
gulp.task('copyPWA', () => {
return gulp.src('./source/manifest.json')
.pipe(gulp.src('./source/sw.js'))
.pipe(gulp.dest('./public/'));
## 加入 manifest.json
準備好專案後就可以在專案底下建立一個 manifest.json
![manifest.json](https://i.imgur.com/1sDpnRH.png)
內容可以填入先前 Google 官方所提供的範例,然後稍微修改一下內容即可:
```json
"short_name": "Sweetaste",
"name": "HexSchool Sweetaste",
"icons": [
"src": "./images/icons/192x192.png",
"type": "image/png",
"sizes": "192x192"
"src": "./images/icons/512x512.png",
"type": "image/png",
"sizes": "512x512"
"start_url": "/index.html",
"background_color": "#3f5d45",
"display": "standalone",
"theme_color": "#3f5d45"
oh,對了,clone 專案之後記得先執行 `npm install`,否則你會無法運行唷~
那你可能會問 icons 呢?當然是自己想辦法生啊~我們偉大的俊儀設計師都提供 Adobe XD 線上稿了,Logo 自己稍微調整一下就可以了。
如果你直接執行 `gulp` 可能會發現 PWA 還是無法運行,因為我們還沒使用 Service Workers 註冊。
## 建立 Service Workers
接下來再專案底下建立 sw.js (Service Workers 縮寫)
![sw.js](https://i.imgur.com/OvP5BqY.png)
內容的話,我們必須先註冊 Service Workers,首先先打開 `js/all.js` 加入以下程式碼
```js
// 判斷瀏覽器是否支援 Service Workers
if('serviceWorker' in navigator) {
// 註冊 Service Workers
// register 是支援 Promise
navigator.serviceWorker.register('./sw.js')
.then((messages)) => {
console.log('Service worker 註冊');
}).cathe((error) => {
console.log(error);
## 修改 hearder
這邊要引入 manifest.json,打開 `layout/header.pug` 加入以下程式碼
```pug
link(rel="manifest", href="./manifest.json")
接下來只需要輸入 `gulp` 就會自動開啟瀏覽器,開啟之後按下 F12 切到 Application 就可以看到 PWA 所需要的都運作了
![manifest](https://i.imgur.com/8n1xUWK.png)
![Service Workers](https://i.imgur.com/YrHGPgZ.png)
但是你會發現 PWA 還不會運作,那麼這邊最主要原因是因為缺少了幾個東西,首先讓我們打開 sw.js,並且寫入以下程式碼:
```js
self.addEventListener('fetch', (event) => {
/* empty */
輸入完之後再重新執行一次 `gulp`,就可以看到 Chrome 的 PWA 模式開啟哩~
![PWA 安裝](/img/20191017092657mgr3g.png)
接下來當你按下安裝之後就可以看到我們已經將甜點電商改成 PWA 應用了
![甜點電商 PWA 版本](/img/20191017093005mh6v2.png)
當然這只是一個 PWA 初體驗功能並沒有很完善,主要只是實作出一個簡易的 PWA 唷~
最後這邊也提供該專案放置位子給予參考
GitHub:[https://github.com/hsiangfeng/Pug-Sweetaste](https://github.com/hsiangfeng/Pug-Sweetaste)
實際線上專案:[PWA 化甜點電商](https://hsiangfeng.github.io/Pug-Sweetaste/)
## 參考文獻
[你的首個 Progressive Web App](https://developers.google.com/web/fundamentals/codelabs/your-first-pwapp)
JavaScript reduce 在做什麼?
陣列方法有很多種,包括 `forEach`、`map`、`filter` 等等,其中 `reduce`算是比較複雜且容易讓人感到困惑的一種方法,因此這篇文章會介紹 JavaScript `reduce` 的功能與基本應用。
## 簡介
關於 `reduce` [MDN](https://firebase.google.com/docs/firestore/?hl=zh-CN) 的定如下:
> The reduce() method executes a reducer function (that you provide) on each member of the array resulting in a single output value.
簡單來說就是 `reduce` 方法跟其他陣列方法(例如:`map`、`filter`)的差別是它會 return 一個值,而不是一個新陣列,這會連帶使 `reduce` 的語法結構跟邏輯與其他方法不太相同。
## reduce 的基礎語法
``` js
Array.reduce(callback[accumulator, currentValue, currentIndex, array], initialValue)
看起來有點複雜,其實就是以下這五個參數:
- accumulator:經由個別 `currentValue` 加總的累計值
- currentValue:`Array` 的個別 item
- currentIndex:`Array` item 的索引
- array:呼叫該 `Array method` 的陣列
- initialValue:預設值,放在 `function` 的最後方,非必填
其中比較特別的是 `accumulator` 與 `initialValue`,在其他的陣列方法裡也少見。用文字敘述可能會不太清楚這些參數的意思,這裡用最簡單的陣列數值加總為例,並預設兩種不同狀況:
### 1. 未提供 `initialValue`(預設值)
``` js
const arr = [1, 2, 3, 4, 5];
const reduceArr = arr.reduce((accumulator, currentValue) => {
return accumulator + currentValue
console.log(reduceArr); // 15
上述範例若未提供預設值,`accumulator`(累計值)就會取陣列的第一個元素也就是 1,而 `currentValue` 就會從陣列的第二個值開始 loop。我們可以執行 `console` 確認數值為何?
``` js
const arr = [1, 2, 3, 4, 5];
const reduceArr = arr.reduce((accumulator, currentValue) => {
console.log(accumulator); // 1, 3, 6, 10
console.log(currentValue); // 2, 3, 4, 5
return accumulator + currentValue
可以清楚看到 `accumulator` 是從 1 開始接收 `currentValue` 的值並開始累計,而 `currentValue` 就從 2 開始 loop,加總方法如以下表格:
![images](/img/176cyd.png)
### 2. 有提供 `initialValue`(預設值)
``` js
const arr = [1, 2, 3, 4, 5];
const reduceArr = arr.reduce((accumulator, currentValue) => {
return accumulator + currentValue
}, 0);
console.log(reduceArr); // 15
可以看到加上預設值 0,雖然 return `value` 跟前面範例一樣是 15,但內部結構已不相同。這裡一樣執行 `console` 確認數值為何?
``` js
const arr = [1, 2, 3, 4, 5];
const reduceArr = arr.reduce((accumulator, currentValue) => {
console.log(accumulator); // 0, 1, 3, 6, 10
console.log(currentValue); // 1, 2, 3, 4, 5
return accumulator + currentValue
}, 0);
這裡的 `accumulator` 變成從 0 開始計算,後面接續 `currentValue` 的值累計。而 `currentValue` 會從陣列的第一個值開始 loop。
![images](/img/27oy3m.png)
那如果預設值不為 0 而是 5,又會有什麼不同的結果呢?
``` js
const arr = [1, 2, 3, 4, 5];
const reduceArr = arr.reduce((accumulator, currentValue) => {
console.log(accumulator); // 5, 6, 8, 11, 15
console.log(currentValue); // 1, 2, 3, 4, 5
return accumulator + currentValue
}, 5);
這裡的 `accumulator` 變成從 5 開始計算,後面接續 `currentValue` 的值累計。return `value` 變成 20。
![images](/img/37q2wj.png)
## 更多 reduce 應用
`reduce` 除了可以處理數字累計之外,還可以做更廣泛的應用。
### 合併陣列
``` js
const arr = [['a', 'b'], ['c', 'd'], ['e', 'f']];
const reduceArr = arr.reduce((accumulator, currentValue) => {
return accumulator.concat(currentValue);
}, []);
console.log(reduceArr); // ['a', 'b', 'c', 'd', 'e', 'f'];
可以看到當預設值為空陣列時,`reduce` 如何透過累計的方式 return 一個合併後的新陣列。
### 計算相同字串的數量並以物件呈現
``` js
const arr = ['a', 'a', 'b', 'c', 'c', 'c', 'e'];
const reduceArr = arr.reduce((accumulator, currentValue) => {
if(accumulator[currentValue]) {
accumulator[currentValue] ++;
} else {
accumulator[currentValue] = 1;
return accumulator;
}, {});
console.log(reduceArr); // { a: 2, b: 1, c: 3, e: 1 }
這一段主要在計算變數 `arr` 內值出現的次數。當預設值為一空物件時,`reduce` loop 過變數 `arr` 後會將 `currentValue` 累計在已繼承預設值的 `accumulator` 上並產生一個新物件。
如果用一般的陣列方法可以這麼寫(以 `forEach` 為例)
``` js
const arr = ['a', 'a', 'b', 'c', 'c', 'c', 'e'];
const obj = {};
arr.forEach(function(char) {
if(obj[char]) {
obj[char] ++;
} else {
obj[char] = 1;
console.log(obj) // { a: 2, b: 1, c: 3, e: 1 }
也可以達到一樣的效果。
其實用這兩種方法的邏輯是一致的,但 `reduce` 的 `initialValue` 可以設為任一型態(數值、物件、陣列),而 `accumulator` 可繼承 `initialValue` 的型態並接收 `currentValue` 計算後的結果。因此雖然程式碼看似沒有簡化很多,但若需要對陣列操作進行比較細膩的比對與計算的話寫起來會較直覺且靈活一些。
## 總結
- 在執行 `reduce` 時需先確認有沒有放 `initialValue`,因為這會直接影響 return 的結果。
- `accumulator`(累計值)是一個特殊的存在,它會反應 `currentValue` 的累計值,這在其他陣列方法比較少見。
- 承上,因為有 `accumulator` 這個參數,使 `reduce` 可以針對陣列的 item 與 item 之間執行一些比較細膩的比對與操作。
## 參考文章
* [MDN reduce](https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce)
* [One reduce() to rule them all — How to use reduce in JavaScript](https://levelup.gitconnected.com/one-reduce-to-rule-them-all-504e1b790a83)
* [Finally Understand the JavaScript Reduce Method](https://alligator.io/js/finally-understand-reduce/)