close

「JavaScript學習筆記」系列文章為小弟我閱讀"Eloquent JavaScript"的筆記,網路上或許已有相同類型的文章,但本文主要目的還是個人筆記用途,或是作者未來腦袋年久失修開始漏東漏西的時候當成快速查閱的工具書使用。所以一些寫給程式入門者的說明不會是本文的重點,有需要的話請查閱原文吧!與我一樣有一點程式基礎,正要開始學習的朋友歡迎參考,如果內容有任何錯誤之處,敬請留言或來信指正,謝謝!

 

JavaScript學習筆記1 - Value, Variable & Control Flow

原始文章連結:http://eloquentjavascript.net/chapter2.html

 

1. Value

1.1 Number

數字基本型別,長度為64bit,可以是整數、浮點數,或是以科學符號表示,例如:

144
9.81
2.998e8 // (即2.998 * 108)

 

1.1.1 Operators of Number

+ add
- substract (or nagative value)
* multiply
/ devide
% mod
()  

 

 

1.2 String

使用雙引號「"」或單引號「'」包住文字便形成一字串型別之值,例如:

"Patch my boat with chewing gum." 

 

1.2.1 特殊字元

使用「\」表示後方接續的字元為特殊字元,例如:

\n 換行
\t TAB
\\ 印出\
\"  印出"雙引號
\' 印出'單引號
 

換行範例:

"This is the first line\nAnd this is the second"

印出雙引號及斜線:

"A newline character is written like \"\\n\"."

 

1.2.2 Operators of String

+ 運算子

字串值無法像數字般進行「減」、「乘」或是「除」,但是可以使用「加」運算子,即「+」,意思是接續字串,例如:

"con" + "cat" + "e" + "nate"

結果為

"concatenate"

更多操作字串的方式會在其他章節中介紹

typeof 運算子

並非所有運算子都是符號,例如typeof運算子,置於一個value前方時會傳回其型別的字串,例如:

typeof 4.5 (should return "Number")

typeof只使用一個運算元,是所謂的「單元運算子」(Unary operator),而四則運算中使用的運算子多為「二元運算子」(Binary operator),其中「-」同時可當單元運算子及二元運算子使用,例如:

- (10 - 2)

 

1.3 Boolean 

1.3.1 比對運算子(Comparison Operators)

布林型別的值只有兩種,即「true」與「false」,對兩個值進行比較時會回傳布林型別的值,用於比對的運算子有:

> 大於(左方運算元大於右方運算元之之簡稱,以下不再重複說明)
< 小於
>= 大於等於
<= 小於等於
== 等於(value)
=== 等於(both value and type, 型別或值均相等時回傳true)
!= 不等於(value)
!== 不等於(value or type, 型別或值有一方不相等時回傳true)

其中==與===之差別在於,==在比對時會做強制轉型再進行比對,而===只有在型別相同時才比對,當型別不同時直接回傳false,故在比較兩個值時,使用===是相對安全的。

 

Number型別之值的比對:

3 > 2 (return true)

2 < 2 (return false)

 

String型別之值的比對:

字串的比對是將布林運算子兩側之字串中包含之字元取出,轉換成Unicode編碼之數字後由左至右逐一比對,

"Aardvark" < "Zoroaster"

 

1.3.2 邏輯運算子(Logical Operators):

邏輯運算子用於對布林值的運算,常見的邏輯運算有AND、OR以及NOT,其中優先權最低者為OR,其次為AND,再來才是NOT,接著就是其餘比對運算子:

&& and 優先權次低
|| or 優先權最低
! not  

範例如下:

((4 >= 6) || ("grass" != "green")) && !(((12 * 2) == 144) && true)

上式用了太多的括號,使得可讀性大大降低,下面簡化過的版本結果相同:

(4 >= 6 || "grass" != "green") && !(12 * 2 == 144 && true)

運算的步驟如下:

(false || true) && !(false && true)

true && !false

true

 

2. Variable

2.1 Expressions and Statements

  在前一個部分所介紹的「值的運算」,即使將運算子套用於運算元上來得到運算過的值,這樣的式子稱為表達式(Expression),所有直接寫出之值(例如:22, "psychoanalysis")是表達式,放在括號中間的表達式是表達式,使用二元運算子對兩個運算元,或一元運算子對一個運算元進行運算,亦為表達式。

  有一個比表達式大的單位稱為陳述(Statement)。一個程式是由許多陳述所組成,大多數的陳述都會以分號(Semicolon, ;)結尾。最簡單的陳述就是在一個表達式後加上分號,例如:

1;

!false;

 

  上例是一個無用的陳述,一個表達式可以是一些用於產生一個值內容,但一個陳述只有在他會改變這個世界時才有意義,可以是在螢幕上印出某些東西,或是以某種會影響之後陳述結果的方式改變程式的內部狀態。這些改變被稱為'Side effects'。上例只會產生1與true之值,並不會改變任何東西。

(事實上,陳述後的分號在某些狀況下是可以被省略的但規則相當奇怪而複雜,因此原文作者強烈建議不要在程式中省略任何一個分號)

  那麼要怎麼保存這些產生的值呢?在JavaScript中提供稱為變數(Variable)的東西,如下例:

var caught = 5 * 5

  變數一定會有一個名字,並且可以用來指向一個值,並且抓住它。上例產生了一個稱為caught的變數,並且使用這個變數儲存由5乘5產生的number value。變數的名稱可以當做表達式使用,亦可以是更大的表達式中的一部分

  識別子var可以來創造一個新的變數,在var之後接著變數名稱。變數的開頭不可以是數字,字元'$'與'_'亦可使用於變數名稱之中,所以$_$是一個正確的變數名稱。

  在一定時間內存在的變數與值的集合稱為環境(Environment),程式初始化的時候,環境不是完全空白的,會存在一些標準的變數。當你的Browser載入一個頁面,會開啟一個新的環境,並將這些標準變數指定給它,這些變數將存活到browser開啟一個新頁面為止。

 

2.2 Function Variable

    許多標準環境提供的值是函數(function)型別。函數是包在一個值內的一塊程式。在browser環境裡,變數alert包含一個在視窗中顯示一個小對話框的函式:

alert("Avocados");

  執行函式的方法是在識別子後方加上括號,每一個產生函數值的表達式可以透過在後方加上括號來執行(invoke)。上例是在視窗中顯示一個對話框,顯示文字"Advocados"。傳入函數中的值稱為參數(Parameter),上例中函式使用了一個參數,在不同函數中可能需要的參數量均不相同,亦有可能不需要參數傳入。

  顯示一個對話視窗是一種side effect,許多函數相當有用,因為他們可以產生的side effect 。但函數也可能是為了產生一個值,在這種狀況下就不需要有side effect。例如下例,Math.max用於在二數中回傳較大者:

alert(Math.max(2, 4));

  當一個函數產生一個值時,這被稱之為回傳。又因為在JavaScript中可以產生值的東西可以被視為表達式,因此函數也可以被當成更大的表達式中的一部分:

alert(Math.min(2, 4) + 100);

  在第三章中將會談到創建自己的函數。

  一些比較常見的標準函數包含:

print() 在console中印出值。
alert() 在螢幕中顯示一個對話框以及文字。
show() 在console中印出關於值與及其型別的資訊(比print提供更多資訊)。
confirm() 在視窗中彈出視窗,詢問使用者的意見,點擊OK時回傳true,點擊Cancel時則回傳false。
prompt() 詢問一個開放性問題,第一個參數是問題的文字,第二個參數是回答的初始值,當使用者按下確定後回傳使用者輸入的string值。

例如:

show(confirm("Shall we, then?"));

詢問使用者"Shall we, then?",在使用者做出選擇後將結果印出。

show(prompt("Tell us everything you know.", "..."));

彈出視窗顯示問題"Tell us everything you know.",初始回答文字為"...",使用者送出後將結果印出。

幾乎對環境中的每一個變數指定一個新的值都是可能的,這可能是有用的,但也可能很危險。如果將8這個值指定給print,那麼你將再也無法使用這個函數印出任何東西(註:Envoronment可以被reset,回復為初始狀態)。

 

2.3 Variable Naming

  變數命名規則已經在上面提過,當一個變數由許多單詞組成時,在可讀性上會出現一些問題,例如:

fuzzylittleturtle, fuzzy_little_turtle, FuzzyLittleTurtle, or fuzzyLittleTurtle.

  第一種所有均小寫,會讓所有單字混在一起,閱讀困難。大部分的JavaScript程式設計師使用最後一種類型,除了第一個單字以外,其他的字母的字首皆大小,相對而言有較高的可讀性。另外,在某些情況裡變數的第一個字母也會使用大寫,像是用於標示一個函數為建構子(Constructor)。關於建構子會在第八章中談到,此處只需注意命名的一致性即可。

  注意要避免使用有特殊意義的單字,例如先前提到的var、while以及for,不會當成變數名稱使用,這些是系統的保留字,以下是官方的保留字列表:

abstract boolean break byte case catch char class const continue debugger default delete do double else enum export extends false final finally float for function goto if implements import in instanceof int interface long native new null package private protected public return short static super switch synchronized this throw throws transient true try typeof var void volatile while with

 

2.4 Undefined Value

  宣告變數時,也可以不指定初始值,此時存取這個變數儲存之值時,會回傳一個特別的值稱為undefined,意思是你存取的變數尚未被定義,並未指向任何地方。不需要回傳值的函式,例如print以及alert也會回傳undefined之值。此外,還有一個相似的值,null,意思是 "這個變數有被定義,但他並未擁有任何值"。

  在實務上,經常需要檢查變數值否有值,此時就會使用something == undefined來檢查。雖然null與undefined並非相同的值,但表達式null==undefined仍會回傳true。接著我們遇到了一些較為tricky的狀況,例如:

 

  以上例子的結果都是true,當比較不同型別之值時,JavaScript使用了一組複雜的規則。一般而言,它會將其中一個值轉為另一個值的型別。然而當null或是undefined出現時,只有兩邊都是nullundefined時才會回傳true

  但如果我們需要檢查一個變值的值是否為false呢?將字串與數字轉換為布林值的規則為0以及空白字串會被視為false,其餘則視為true。因此,表達式 variable == false 在其值為0或者""時同樣會回傳true。

  在這種狀況下,我們不希望任何自動型別轉換發生。有兩個額外的運算子===以及!==可以使用,他們檢查兩個值是否型別與值均精確相等:

以上所有比較結果均為false。

 

3. Flow Control

3.1 IF Condition

  僅有一個條件判斷時,使用單一if判斷即可;當有多個條件需判斷時,可依情況在後方串接其他if判斷如下方格式:

簡單的使用範例如下:

 

3.2 While Loop

  while識別子可以創造一個迴圈,會讓一段程式執行數次,第二個部分,是while傳入的expression是用來判斷迴圈是否該繼續執行,當expression的值為true時繼續,false則終止,第三個部分是迴圈中想重復執行的陳述,使用大括號{}將這些陳述包起來:

當想要執行的陳述只有一行時,可以簡化為:

大括號用於將陳述組合成一個block,對於block以外的世界而言,block算是一個單一的陳述

 

3.3 For Loop

  在for迴圈後的括號內,必須包含兩個分號,第一[個分號前的部分用於初始化迴圈,通常藉由定義一個變數;第二個分號前的部分用於檢查迴圈是否該繼續執行;最後,第二個分號後用來更新迴圈的狀態(通常是更新宣告的變數)。

例如:

初始化變數number=0, number<=12則繼續執行。

  有時候迴圈不見得總是需要一直執行到最後,此時break識別子可用於結束迴圈的執行,如下例:

  上例省略了檢查迴圈控制變數的條件,這表示迴圈的結束完全依賴break識別子。上例可以進一步被簡化為:

  在這個例子裡,迴圈的body是空的,分號可以用來產生空白的陳述。此處這個迴圈唯一的作用就是讓current的值遞增至目標值。接著讓我們看看break在while迴圈中的使用:

  上面的練習是關於使用while迴圈檢查問題的答案,直到回答正確才結束迴圈。此處要注while(true)會創造一個不會自己停止的while迴圈,雖然檢查true=true看起來蠻傻的,不過這是用來重複執行程序的一個小技巧。由於第一個if中有兩個陳述,因此使用了大括號,但其他的if/else只有一個陳述,看起來有些不平衡,不過這算是設計上的風格,端看個人的喜好。

  下面的例子避開了這個情況(arguably nicer),但是沒有使用break。

  在if/for/while陳述中使用的條件判斷不需要為布林值,他們在被檢查之前會被自動轉換為布林值。這代表數字0數字NaN(稍後部分會討論)、空字串""nullundefined以及false都會被視為false。

  由於其他的值都會被視為true,使得在多數情況中都可以做直觀的比對。如果已知一個變數可能會包含字串或是null,我們可以用以下的方式做簡單的檢查:

…,除了當maybeNull的值為空字串""時。由於空字串是會被判定為false,因此不會印出任何東西。但這可能是錯誤的,端看你想做的是什麼。明顯的寫出=== null 或是=== false在這類例子中可以避免這些微妙的錯誤。類似的問題也可能發生在number型別的值可能為0

 

4. 註解

  上例中談到了「mystery code」的程式碼對你而言可能有些陌生。在程式中加入隔外的文字是很有用的,最常見的用法就是加入一些人類可讀的解釋在程式之中。

  這類型的文字稱為「註解」。使用的規則如下:

1. 使用「/*」起始,一直到「*/」結尾之間的文字。

2. 使用「//」起始直到該行結尾的文字。

 

5. 自動轉型

   除了布林值的運算之外,還有一些其他的狀況會觸發自動轉型。

1. 如果你將一個非字串的值與字串相加(字串串接),該值在被串接前會自動轉型為字串

2. 如果你將一個數字與字串相乘,javascript會試著將字串轉換為數字,見以下的例子

  最後一個陳述將會印出一個特殊值NaN,也就是「not a value(非數字)」,其型別為number(可能看起來有點矛盾)。在這個例子裡,這解釋為「"strawberry"並非數字」。NaN具有一些特殊的性質,例如:

1. 所有對NaN的數學運算產生的結果都會是NaN,這也是為什麼在本例中被乘以5之後仍然得到NaN這個結果。

2. 檢查一個值是否為NaN必須使用isNaN函數NaN == NaN 的結果為false

3. NaN是另一個(也是最後一個)轉為布林值結果為false的數值。

  這些自動轉型非常方便,但看起來也相當怪異且容易發生錯誤。即使加「+」與乘「*」都是數學運算子,但他們在上例中表現出來的行為是完全不同的。在作者的程式裡,他經常使用「+」串接字串與非字串,但要求自己不使用「*」以及其他數學運算子在數字與字串上。將數字轉為字串總是可行且直覺的,但將字串轉為數字則並非總是可行。我們可以使用Number強制轉型這種明顯的作法來將字串轉為數字,以強調可能會得到NaN的風險。

 

6. 布林運算子「&&」與「||」的特性

  稍早當我們討論布林運算子「&&」以及 [ ||」時,作者聲稱他們會產生布林值,這其實是有點過度簡化的。如果你將他們使用在布林值上,他們確實會回傳布林值。但是,當他們也可以被使用在其他類型的的數值上,在這種狀況裡,他們就會回傳其中一個參數

  「||」運算子實際上做的事情是:先檢查左邊的運算元,如果將其轉換為布林值結果為true,則回傳左邊的運算元,否則的話回傳右邊的運算元。我們可以檢查看看看看應用在布林值上這件事是否是正確的。為什麼他會這樣運作呢?原因是因為這非常的實用,看看以下例子

  如果使用者按下「cancel」或是以其他方式關閉「prompt」對話,則「input」值將會是「null」或是空字串。當轉換為布林值時兩者都會變成false。表達式「input || "dear"」可以被解讀為「input變數的值,或是字串"dear"」。這是一個產生「falback」(備援?)值的簡易方法。

  「&&」也以類似的方式運作。當左邊的運算元轉為布林值的結果為false時回傳該值,否則的話回傳右邊的運算元。

  這兩個運算元有一個共同的特性,就是在他們右邊的運算元只有在需要的時候才會被檢查。在「true || x」這個例子裡,無論x的值是什麼,結果都會是true,所以x永遠不會被檢查,如果它有side effect的話永遠不會被觸發。「false && x」也是相同的情況,簡單的例子如下。

 

arrow
arrow
    文章標籤
    javascript
    全站熱搜

    Hubert 發表在 痞客邦 留言(2) 人氣()