Open pychiang opened 6 years ago
其中要注意在幫 key 命名的時候,不能使用數字做為第一個字母,雖然使用 bracket notation 沒有差別,但是在使用 dot notation 的時候會造成讀不到資料。
不能使用 => 盡量不要使用,畢竟你後面都說可以用 bracket notationa 了,哪來的「不能」XD
如果有多個單字組成的 key,則要用 camelCase 來命名
也可以用 under score 喔,例如說 home_phone_number
剛好看這個教學影片之前在 Udacity Intro to JavaScript 上重新複習 JavaScript,又看了胡立老師的影片後,有種豁然開朗的感覺啊~不過作業依舊寫得很慢 :sob:
兩個小時的教學影片含有大量的資訊量,所以筆記很~~長,寫得頭昏 :joy:
物件 (object)
物件為一種資料型態,用大括號
{}
包起來。在物件裡面可以包含屬性 (property) 或是函式 (method),彼此之間用逗號相隔。以下為一個基本物件形式:可以看見物件的值 (value) 可以是各種型態,字串、數字、陣列、函式、布林,甚至是另一個物件都可以。
想要取得物件裡面的值有兩種型式:
其中要注意在幫 key 命名的時候,盡量不要使用數字做為第一個字母,雖然使用 bracket notation 沒有差別,但是在使用 dot notation 的時候會造成讀不到資料。
如果 key 有兩個單字以上組成,則不能使用空白或是橫線
-
來連接兩個單字,同樣在使用 dot notation 的時候會造成讀不到資料,如果有多個單字組成的 key,則要用 camelCase 來命名。camelCase 指的是第一個單字開頭小寫,第二個單字以後則開頭大寫,就像駱駝的駝峰一樣,例如:friendsName、homePhoneNumber,或是用底線_
來連接單字,例如 home_phone_number。JSON (JavaScript Object Notation)
JSON 是一種資料格式,常見於 API(Application Programming Interface,應用程式介面)中,有利於前、後端彼此之間交換資料。其中要注意的是,JSON 檔案中的 key 必須用雙引號包起來,物件裡則不用。專案中的
package.json
就是典型的 JSON 檔案:兩個等號 vs 三個等號
雖然在 JavaScript 裡宣告變數的時候不用指定資料型態,但是 JavaScript 的底層還是有型態之分的。只有三個等號時才會嚴格的比較兩者間的數值與型態,所以胡立老師說,忘記兩個等號吧~
如果要轉換資料型態的話,就要用其他的方法,例如:
或是利用函式:
等號背後的意義
在 JavaScript 裡,有三種資料被存在記憶體位置而不能用等號來比較是否相等:
所以可以看到下面的例子,陣列跟物件不相等:
雖然我們眼睛看到的陣列跟物件長得一模一樣,但是在 JavaScript 底層,其實是把它們兩個分別存放在不同的記憶體位置,所以兩者相比時就不相等。如果要比較物件、陣列、或函式的時候,則要用手動比較。
物件的例子:
因為物件存在記憶體位置,所以當設
var b = a
時,b 跟 a 對應到同一個記憶體位置,下一行b.name = "hi"
時,把記憶體原本儲存{name: "yo"}
改成儲存{name: "hi"}
,所以 a 的數值也跟著改變。可以看到最後console.log(a == b) //prints true
,照理來說物件無法用等號比較,但因為 a 跟 b 對應到的記憶體位置變成相同的了,所以用等號相比也能相等。數字的例子:
因為數字不是存在記憶體位置,所以當設
var b = a
時,b 對應到 a 原本的數字 10,下一行b = 30
只有改變 b,而 a 並未改變。模組 (module)
當專案越來越大時,就會重複用到同樣的物件或函式,與其浪費時間在每個檔案內寫一模一樣的東西,倒不如把重複的東西另外寫在一個檔案,然後讓其他檔案共享資源,這個時候就需要用到模組。
模組基本上就是輸出跟輸入的概念,利用 Node.js 內建的
module.exports
輸出,然後require
輸入,下面是一個簡單的範例。在
utils.js
檔案內:在
index.js
檔案內:其中
./
表示utils.js
跟index.js
在同一個資料夾底下。除了可以輸出一個函式,也可以把多個函式用物件包起來一起輸出。 在
utils.js
檔案內:在
index.js
檔案內:因為在
utils.js
檔案內有寫log
的函式,所以可以取代console.log
。課程裡的測試檔案則是用
exports
跟import
,這兩個是 ES6 的語法,在下面會有解釋。 其中胡立老師寫 test case 的時候用到兩種不同的等於函式toBe()
跟toEqual()
,這兩者的差別在於toBe()
就等於是兩個等號==
,而toEqual()
則可以檢查陣列或物件是否相等。作用域 (scope)
作用域 (scope) 就是變數的生存範圍,分為全域 (global scope) 跟函式域 (function scope)。
下面的例子可以看到在 function scope 的變數無法在 global scope 中呼叫到:
另外一個例子可以更清楚看出在不同 scope 裡的變數的生存範圍:
其中要注意的是,宣告變數時一定要加
var
,否則 JavaScript 會把那個變數自動改成全域變數,容易造成 bug 產生。變數也可以拿來存函式:
所以函式可以被當成參數傳入另外一個函式裡。 被當成參數的函式有時會以匿名函式 (anonymous function) 的型式出現,之所以稱作匿名函式是因為它沒有名稱。
其實上面例子的後半部函式跟下面的例子是表示一樣的東西:
ES6 語法
上次上新手到中手前端加強班的時候,那時候很怕 ES6 語法,每次看胡立老師教學的時候就好像在看天書一樣,看了幾個解說 ES6 的文章也是看不太懂,這次胡立老師講解之後卻變得容易許多,可能之前有看過比較不陌生了,不過在實際運用上還要多練習。
1. 宣告變數的方式
const
跟let
在 ES6 裡多加了const
跟let
這兩個宣告變數的方法。其中的差別在:const
:給定一個值之後就不能再變了,例如:let
:大部分的時間都跟var
是一樣的,除了let
的生存範圍是在大括號的區塊範圍內 (block scope)。而var
的生存範圍是一個 function,如果把整個檔案視為一個大的 function 的話,一個變數的生存範圍其實是一個 function。這裡沒有任何 function,所以
var test
不受if
的大括號範圍侷限:如果改成
let
就只生存在if
的區塊內:所以
let
的生存範圍可以是 function、if
判斷、或for
迴圈。2. Arrow function Arrow function 跟原本的寫法有細微的差距,但是現在會把事情變得太復雜,所以之後胡立老師才講解。下面四種寫法都是一樣的:
3.
import
跟export
Node.js (8.9.4) 還沒支援import
跟export
,所以要安裝 Babel。關於 Node.js 跟 Babel 是什麼可以參考我以前寫的這一篇筆記,雖然裡面是在講 Webpack,但是有不少東西都是一樣的。所以先安裝 Babel CLI 跟 preset:
然後創一個
.babelrc
的檔案,然後在裡面放進:要執行的時候輸入下面指令,就可以執行較新的語法:
環境設定好之後就可以來講
import
跟export
了。前面有提到module.imports
跟require
,其實兩個的概念是一樣的。 在utils.js
檔案裡,如果只輸出一個函式:在
index.js
檔案裡可以輸入剛才的函式:在
utils.js
檔案裡,如果輸出多個函式:在
index.js
檔案裡可以輸入剛才的兩個函式:4. Template string 有時候需要用到字串相加,但當字串很長又有變數跟其他符號在裡面的時候,可讀性就會降低,而 template string 就是用來改善這個問題的。
所以把要相加的字串跟變數放在
`
符號 (backtick) 裡面(鍵盤左上角跟波浪號~
一起的那個符號),然後把變數用$
跟{}
包起來就可以了,省去加號+
。最厲害的是還可以直接換行,省去使用\n
,真是太方便的方法了啊!5. Destructing 跟 spread opeartor 在一個物件裡,要把數值宣告成額外的變數的話可以用 destructing 寫法:
而 spread operator 就是用
...rest
去省略一個物件或陣列裡面的元素寫法,例如在剛才的物件裡多加兩個元素:在陣列中也可以用
...rest
還可以搭配first
:數學類常用函式
Math.random()
:產生 0 <= n < 1 之間的隨機小數,可以依需求乘倍數。例如:Math.floor()
:往下取整數,無條件捨去小數點後面位數Math.ceil()
:往上取整數,無條件進位parseInt()
:把字串變數字console.log(parseInt(a) === 50) //prints true
Math.sqrt()
:開根號字串類常用函式
.length
:用來取字串的長度,其實不是函式.toUpperCase()
:把字母變成大寫,如果原本就是大寫的話就維持大寫.toLowerCase()
:把字母變成小寫,如果原本就是小寫的話就維持小寫.replace()
:取代字串,第一個參數是要被取代的字串,第二個參數是新的字串也可以只取代字母,但只會取代第一個字母:
如果要取代字串內的所有指定的字母,則要用
/ /g
包起來:如果要取代的字母不只一個,則在
/ /g
裡面再用 OR operator|
,或是用[]
包起來:.indexOf()
:顯示出參數字母第一次在字串中出現的位置.slice()
:切字串用的,當傳一個參數時,表示要從字串前面切掉幾個字母,印出剩下的:當傳兩個參數的時候,第一個參數是開始切的 index,第二個是結束的 index(但不包含),印出切出來的字母:
如果第一個參數的 index 比第二個參數的 index 還大的話,會回傳一個空字串。
.split()
:把字串轉換成陣列用的,可以按照傳進的參數符號把字串切成陣列:如果傳入空字串的話,會把字串變成陣列:
陣列類常用函式
.length
:用來取陣列的長度,其實不是函式.map()
:loop over 陣列裡的每個元素,每個元素都執行參數裡的函式,再回傳一個新的陣列console.log(arr.map(twice)) //prints [2, 4, 6, 8, 10]
可以用 ES6 語法的 arrow function 簡化:
在 ES6 語法裡,函式只有一行的話不用使用大括號
{}
,而且return
也可以省略:在 ES6 語法裡,函式只有一個變數也可以省略旁邊的小括號
()
,所以最後可以省略成這樣:而且可以一直連續回傳,簡化後的寫法可讀性變得高許多:
.filter()
:回傳 true 會被留下,false 會被拿掉.join()
:把陣列內的元素加起來變一個字串,參數內傳用來連接的符號,如果不傳參數,默認是逗號.push()
:在陣列後面新增一個元素.sort()
:排陣列內的順序,預設是由小到大.sort()
是用排字串的方法來排數字,所以如果混合位數的數字排列,只看第一位數字大小.sort()
可以傳入函式參數,自訂排序的規則。如果要由最小數字排到最大數字:.indexOf()
:跟剛才的字串.indexOf()
一樣,用來找參數第一次在陣列中出現的位置,如果回傳-1
的話,則表示找不到這個值.reduce()
:類似把陣列加總,可以參考 MDN - Array.prototype.reduce()(因為我也還不太懂 XD)上面函式的運算是這樣:
痛苦會過去,筆記會留下,終於寫完了 :joy: :tada: :tada: :tada: