动态

详情 返回 返回

前端工程師復健筆記-JavaScript 核心深度複習-作用域與詞法環境 - 动态 详情

作用域與詞法環境

這是一個非常核心的JavaScript概念。我們來詳細地解釋一下全局作用域、函數作用域和塊級作用域的區別。

核心概念:作用域

作用域 就是變量、函數和對象的可訪問性範圍。換句話説,它決定了代碼中不同部分的變量可見性。


1. 全局作用域

  • 定義:在任何函數或代碼塊 {} 之外定義的變量或函數,都擁有全局作用域。
  • 生命週期:從定義開始,直到頁面關閉。
  • 訪問性:在腳本中的任何地方(包括函數內部和代碼塊內部)都可以訪問和修改。

示例

// 全局變量
var globalVar = "我是全局變量";
let globalLet = "我也是全局變量(但用let聲明)";
const globalConst = "我也是全局變量(但用const聲明)";

function myFunction() {
  console.log(globalVar); // 在函數內部可以訪問
  console.log(globalLet); // 可以訪問
  console.log(globalConst); // 可以訪問
}

myFunction();
console.log(globalVar); // 在函數外部也可以訪問

注意

  • 在瀏覽器中,全局作用域是 window 對象。因此,使用 var 聲明的全局變量會成為 window 對象的屬性(例如 window.globalVar),但使用 letconst 聲明的則不會。

2. 函數作用域

  • 定義:在函數內部聲明的變量擁有函數作用域。
  • 生命週期:在函數被調用時創建,在函數執行完畢後銷燬。
  • 訪問性:只能在定義它們的函數內部訪問。函數外部無法訪問。

示例

function myFunction() {
  // 函數作用域變量
  var functionScopedVar = "我在函數內部";
  let functionScopedLet = "我也在函數內部";
  const functionScopedConst = "我同樣在函數內部";

  console.log(functionScopedVar); // 可以訪問
  console.log(functionScopedLet); // 可以訪問
  console.log(functionScopedConst); // 可以訪問
}

myFunction();
// console.log(functionScopedVar); // 報錯:functionScopedVar is not defined
// console.log(functionScopedLet); // 報錯
// console.log(functionScopedConst); // 報錯

關鍵點

  • 無論使用 varlet 還是 const 在函數內部聲明的變量,都具有函數作用域。

3. 塊級作用域

  • 定義:由一對花括號 {} 創建的代碼區域,例如 ifforwhile 語句或單獨的一個 {}。使用 letconst 聲明的變量僅限於其所在的塊內。
  • 生命週期:在代碼塊被執行時創建,在代碼塊執行完畢後銷燬。
  • 訪問性:只能在定義它們的代碼塊內部訪問。

示例

if (true) {
  // 這是一個塊
  var varVariable = "我用var聲明";
  let letVariable = "我用let聲明";
  const constVariable = "我用const聲明";

  console.log(varVariable); // 可以訪問
  console.log(letVariable); // 可以訪問
  console.log(constVariable); // 可以訪問
}

console.log(varVariable); // 可以訪問!因為var沒有塊級作用域
// console.log(letVariable); // 報錯:letVariable is not defined
// console.log(constVariable); // 報錯:constVariable is not defined

關鍵點

  • var 沒有塊級作用域,它會“穿透” iffor 等塊級語句,直接成為其所在函數或全局作用域的變量。
  • letconst 擁有塊級作用域,這是 ES6 引入它們的重要原因之一。

對比表格

特性 全局作用域 函數作用域 塊級作用域
定義位置 所有函數和塊之外 函數內部 {} 內部(如 if, for, while)
關鍵字 var, let, const var, let, const letconst
生命週期 頁面關閉時銷燬 函數執行完畢後銷燬 代碼塊執行完畢後銷燬
外部訪問 任何地方都可訪問 不可在函數外訪問 不可在塊外訪問
var 表現 成為全局變量,是window的屬性 函數內有效 無視塊,提升到函數/全局頂部
let/const表現 全局變量,但不是window的屬性 函數內有效 遵守塊,塊外無法訪問

重要補充:變量提升與暫時性死區

  1. var 的變量提升
    var 聲明的變量會被提升到其作用域(函數或全局)的頂部,但只提升聲明,不提升賦值。在賦值前訪問會得到 undefined

    console.log(hoistedVar); // 輸出:undefined (而不是報錯)
    var hoistedVar = "我被提升了";
  2. letconst 的暫時性死區
    letconst 雖然也有提升,但它們不會被初始化。從塊開始到聲明語句之間的區域稱為“暫時性死區”,在此區域訪問變量會拋出引用錯誤。

    console.log(deadZoneLet); // 報錯:Cannot access 'deadZoneLet' before initialization
    let deadZoneLet = "我在死區裏";

總結

  • 全局作用域是最大的容器,隨處可訪問,但要避免污染全局命名空間。
  • 函數作用域將變量隔離在函數內部,是組織代碼的基礎單元。
  • 塊級作用域(由 let/const 實現)提供了更精細的變量控制,尤其是在循環和條件語句中,避免了 var 帶來的一些怪異行為。

在現代JavaScript開發中,推薦始終使用 letconst 來聲明變量,以避免變量提升和塊級作用域相關的問題,使代碼更可預測和易於維護。

user avatar Leesz 头像 haoqidewukong 头像 yinzhixiaxue 头像 freeman_tian 头像 jingdongkeji 头像 qingzhan 头像 kobe_fans_zxc 头像 chongdianqishi 头像 longlong688 头像 huajianketang 头像 xinggandemuer_b5u1v2 头像 huichangkudelingdai 头像
点赞 187 用户, 点赞了这篇动态!
点赞

Add a new 评论

Some HTML is okay.