0%

JavaScript Chap.4 : 變數的宣告與提升

JavaScript Chap.4 :變數的宣告與提升

在這篇文章會學到

  • 變數宣告 var、let、const 差別
  • 變數作用域是什麼
  • 提升(Hoisting)是什麼

變數宣告 var、let、const 差別

還記得曾經面試時被問過: 請說明 var是什麼?
當時我很自然回答了 - 全域變數, 那時還以為是正確答案,但其實是大錯特錯。
只要在window下宣告,不論使用var、let 都是全域變數,正解應該回答為 它的作用域是在函式內。

這三個變數宣告是最容易讓初學者搞混,也無法一時說出差別的。

用發明先後順序可分為

  1. var
  2. let 和 const // ES6後開始使用

相同區域能否重覆宣告 可分為
var => 可重覆宣告 // 也代表會汙染到全域屬性
let => 不可重覆宣告

變數宣告 是否能改變 可分為
var => 可改變數值
let => 可改變數值
const => 不可改變數值

作用域 不同可分為
var => 函式作用域
let => 區塊作用域
const => 區塊作用域

因此除非是就專案或是初學時期使用,否則都推薦使用let、const 作為變數宣告使用。

作用域是什麼

作用域也就是指變數被宣告後可使用的區域。

在 JavaScript 又可分為 全域環境函式環境區塊環境

在外層(全域環境)宣告變數可以傳進 內層(函式或區塊) 使用

但在內層宣告變數卻不能在外層使用 // 很重要

有一個經典考題如下

1
2
3
4
5
for(var i = 1; i <= 5; i++) {
setTimeout(function timer() {
console.log(i);
}, i * 1000);
}

請問會出來什麼?
是 1、2、3、4、5嗎?

錯~ 是6、6、6、6、6。
~
~
~
~
~
那如果希望答案是 1、2、3、4、5 要怎麼改?
~
~
~
~
~
答案為 將var 改成 let ,就可以讓數值保留在區塊中,而不污染至全域。

提升(Hoisting)是什麼

它是一種釐清 JaveScript 在執行階段內文如何運行的思路(尤其是在創建和執行階段)。然而,提升一詞可能會引起誤解:例如,提升看起來是單純地將變數和函式宣告,移動到程式的區塊頂端,然而並非如此。變數和函數的宣告會在編譯階段就被放入記憶體,但實際位置和程式碼中完全一樣。

直接舉個例子來說:

1
2
3
4
5
6
7
8
9
let num = 6 

function add(){
num+=3 ;
console.log('2:',num);
}

console.log('1:',num);
add();

答案為 1:6、2:9。

其中
創造階段為
let num;
建立 function add

執行階段為
let 賦予6的數值給num
執行 console.log(1…)
執行 add()
執行 console.log(2…)

那如果題目改成

1
2
3
4
5
6
7
8
function add(){
num+=3 ;
console.log('2:',num);
}

console.log('1:',num);
let num = 6
add();

答案為何??
~
~
~
~
~
答案為 1: num is undefined ,2:9

因為在執行console.log(1..)時,let尚為取得數值。

而外再加碼一題~(2023/03/18更新)

1
2
3
4
5
6
7
8
9
10
11
12
13
console.log(1, NumA(3)); 

function NumA(x){
return x * x;
}
console.log(2, NumA(3));

console.log(3, NumB(4))

const NumB = function(x){
return x * x;
}
console.log(4, NumB(4))

答案為何??
~
~
~
~
~
答案為 1: 3 ,2:3 ,3: NumB() is undefined ,4: 4

因為在function NumA 在Hoisting 階段時 就已建立好函式
因此在執行階段時 console.log 放函式前 一樣能被執行

而 function NumB 則是宣告成變數,但尚未被賦值成函式
故 console.log 放函式前 則會顯示 undefined

以上就是本篇想說的,謝謝大家收看。