文章中英模式
布魯斯前端JS面試題目 - JavaScript 作用域
解析 JavaScript 中的作用域機制、變數傳遞方式,以及立即執行函式(IIFE)的應用。掌握塊級作用域、函數作用域、經典 for 迴圈問題與解決方案。
文章中英模式
懶得看文章?那就來看影片吧
作用域是什麼?
作用域就像是一個變數的「活動範圍」,決定了變數在哪裡可以被使用。
三種作用域
- 1.
塊級作用域
:用{}
包起來的區域 - 2.
函數作用域
:函數內部的區域 - 3.
全域作用域
:最外層的區域
// 塊級作用域
{
let x = 1; // 只能在這個大括號內使用
}
console.log(x); // 錯誤!x 不存在
// 函數作用域
function test() {
var y = 2; // 只能在這個函數內使用
}
console.log(y); // 錯誤!y 不存在
// 全域作用域
let z = 3; // 到處都可以使用
變數傳遞的兩種方式
1. 傳值(基本型別)
- •複製一份新的值
- •修改新變數不會影響原變數
2. 傳參考(物件型別)
- •複製的是「地址」
- •修改新變數會影響原變數
// 傳值
let a = 1;
let b = a; // 複製一份 1 給 b
b = 2; // 修改 b 不會影響 a
console.log(a); // 還是 1
// 傳參考
let obj1 = { x: 1 };
let obj2 = obj1; // 複製的是地址
obj2.x = 2; // 修改 obj2 會影響 obj1
console.log(obj1.x); // 變成 2 了!
IIFE 是什麼?
IIFE(立即執行函式)就是一個馬上執行的函式,常用來:
- •保護變數不被外面使用
- •解決 for 迴圈的問題
// 基本用法
(function() {
let secret = '不能說的秘密';
console.log(secret); // 可以印出
})();
console.log(secret); // 錯誤!外面看不到
🔥 常見面試題目
(一) let
和 var
差在哪?
解答:主要差異有:
- •
let
一定要先宣告才能用,var
可以先用後宣告 (hoisting提升,用let可以及時發現bug) - •
let
在宣告前使用會直接報錯,讓你知道寫錯了 - •
let
不會變成全域變數(不會掛在 window 上)
(二)經典的 for 迴圈面試題 - 以下輸出為何?
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 1000);
}
解答:會是 3, 3, 3
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 1000);
}
// 輸出:3, 3, 3
為什麼會這樣?
•var
沒有塊級作用域
•當 setTimeout
執行時,迴圈已經跑完了
•此時 i
的值已經是 3
•所以三個 setTimeout
都印出 3
解決方式
1. 使用 IIFE 的解法
for (var i = 0; i < 3; i++) {
(function(j) {
setTimeout(() => console.log(j), 1000);
})(i);
}
// 輸出:0, 1, 2
為什麼這樣可以?
•IIFE 創造了一個新的作用域
•每次迴圈都把當下的 i
值傳進去
•每個 setTimeout
都有自己的 j
值
•所以可以正確印出 0, 1, 2
2. 使用 let
的解法(最推薦)
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 1000);
}
// 輸出:0, 1, 2
為什麼這樣可以?
•let
有塊級作用域
•每次迴圈都會創建一個新的 i
•每個 setTimeout
都記住自己那次的 i
值
•所以可以正確印出 0, 1, 2
(三)為什麼要用 IIFE?
解答:IIFE 創造了一個新的作用域,可以:
- •保護變數不被外面修改
- •讓程式碼更安全、更模組化