關於 JavaScript 中的 function、宣告(var / let / const)、Hoisting 的觀念筆記。
Function
一連串的處理、一群指令的集合。
定義 function() 起手式
定義有名字的 (一般)function
function functionName(參數1, 參數2
...)
{
...
執行內容
return 回傳值 (非必要)
}
定義沒有名字的 (匿名)function
function (參數1, 參數2
...)
{
...
執行內容
return 回傳值 (非必要)
}
有名字 V.S 沒名字的 function ?
- 有名字的 function 可更方便的在不同的地方被呼叫。
沒名字的(匿名)function
可存進變數裡,透過變數被呼叫。
var total = function() { ... }
或透過 IIFE 的方式執行: (感謝泰安老師補充、Eureka解惑)
(function() { ... })()
呼叫時的差異:
有名字 function 在其前或後,都可呼叫成功。
指給變數的匿名函數,在呼叫時必須在其變數定義行之後才可呼叫。
Function被呼叫時
function myFunction(x) {
return x
}
console.log(myFunction)
// 印出整個function code
console.log(myFunction(2))
// 印出function回傳值
基礎寫法
- 定義與呼叫function時一定要加()
- 回傳值要加 return
- return行之後的程式碼都不會執行(return表function結束)
箭號涵式 Arrow Function
函式運算式
function show(text){ console.log(text) }
箭號涵式
- 寫法1 : (參數)=>(回傳值)
> 宣告 函數名稱 (參數1,參數2) => ( 回傳值 )
- 回傳值可以省略return 參數只有一個的時候可以省略括號 > 宣告 函數名稱 參數1 => ( 回傳值 )
- 參數只有1個的時候可以省略() > 宣告 函數名稱 () => ( 回傳值 )
- 沒有參數的時候不能省略括號
寫法2 : (參數)=>{涵式內容} > 宣告 函數名稱 (參數1,參數2) => {
> 涵式內容 > ... > > }例1:
var show = (text) =>{ console.log(text) }
例2 (內裡匿名涵式):
setTimeout(()=> { console.log('text') }),1000);
- 寫法1 : (參數)=>(回傳值)
> 宣告 函數名稱 (參數1,參數2) => ( 回傳值 )
Hoisting 提升
先使用變數才宣告 var 時,不會噴錯、能執行但變數 = undefined
因為只有提升宣告、沒有提升定義值
console.log(num) var num = 1 // 是"undefined"、不是"Error"也不是1
其他示例
// 先使用變數再let宣告與賦值 console.log(num1) let num1=1 // Uncaught ReferenceError: Cannot access 'num1' before initialization
// 先使用變數再var宣告與賦值 console.log(num2) var num2 = 1 // undefined
// 先使用變數才賦值但無宣告 console.log(num3) num3 = 2 // Uncaught ReferenceError: num3 is not defined
// 先使用變數才var宣告但無賦值 console.log(num4) var num4 // undefined
// 先使用變數才let宣告但無賦值 console.log(num5) let num5 // Uncaught ReferenceError: Cannot access 'num5' before initialization
Scope 作用域
- global scope - 包含function外(全域)
- function scope - function內
- block scope - block 內
宣告變數&常數-var / let / const
var | let | const | |
---|---|---|---|
意義 | 宣告變數 | 宣告變數 | 宣告常數 |
宣告時 | 可以先不指定值 | ← (同var) | 必須指定值 |
宣告後 | 可再次指定值 | ← (同var) | 不可改變值 |
宣告後 | 可再次宣告 | 不可再次宣告 | 不可再次宣告 |
範例 | var x var x = 2 | ← (同var) | const PI=3.14159 |
Scope 作用域 | 該涵式區塊 | 該程式區塊{大括號內} 包含迴圈/判斷 | ← (同let) |
- 變數宣告不用指定類型
可以隨時改變變數值的類型(儘量避免)
型別資訊只存在在值或物件本身,變數本身沒有型別 - 早期只能用var宣告變數,ES6增加 let、const
- 如果沒有宣告而直接賦值(num = 2)也會成功
因為 JS 自動視為全域變數宣告(但最好不要這樣)
print = (content) => {
console.log(content)
}
Var
var 沒有 function 時,scope 為整塊
for(var i=0 ; i<5 ; i++){ print(i) //成功取得 i (=1、2、3、4) } print(i) //成功取得 i (=5)
var 在 function 內時,scope = function 內
function 外讀不到function test(){ for(var i=0 ; i<5 ; i++){ print(i) //成功取得 i (=1、2、3、4) } } print(i) //無法取得 i
Let
let scope 只在{ }內
{ } 外就讀不到了for(let i=0 ; i<5 ; i++){ print(i) //成功取得 i (=1、2、3、4) } print(i) //無法取得 i
參考資料
- [arrow function|MDN](https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Functions/Arrow_functions)
- [Hoisting|MDN](https://developer.mozilla.org/zh-TW/docs/Glossary/Hoisting)
- [IIFE|MDN](https://developer.mozilla.org/zh-TW/docs/Glossary/IIFE)
- [ASTRO X 五倍紅寶石 全端工程師實戰訓練營 | 蘇泰安](https://taian.su/)