前言
作用域決定了變量的生命周期和可見性,變量在作用域范圍之外是不可見的。
JavaScript 的作用域包括:模塊作用域,函數(shù)作用域,塊作用域,詞法作用域和全局作用域。
全局作用域
在任何函數(shù)、塊或模塊范圍之外定義的變量具有全局作用域。可以在程序的任意位置訪問全局變量。
當(dāng)啟用模塊系統(tǒng)時(shí),創(chuàng)建全局變量會變得困難,但仍然可以做到這一點(diǎn)。可以在 HTML 中定義一個(gè)變量,這個(gè)變量需要在函數(shù)之外聲明,這樣就可以創(chuàng)建一個(gè)全局變量:
<script>let GLOBAL_DATA = { value : 1};</script>console.log(GLOBAL_DATA);當(dāng)沒有模塊系統(tǒng)時(shí),創(chuàng)建全局變量會容易很多。在任何文件中的函數(shù)外聲明的變量都是全局變量。
全局變量貫穿于程序的整個(gè)生命周期。
另一種創(chuàng)建全局變量的方法是在程序的任意位置使用 window 全局對象:
window.GLOBAL_DATA = { value: 1 };這樣 GLOBAL_DATA 變量會隨處可見。
console.log(GLOBAL_DATA)
不過你也知道這種做法是不好的。
模塊作用域
如果不啟用模塊,在所有函數(shù)之外聲明的變量是全局變量。在模塊中,在函數(shù)外部聲明的變量都是隱藏的,除非顯式導(dǎo)出,否則不可用于其他模塊。
導(dǎo)出使函數(shù)或?qū)ο罂捎糜谄渌K。在這個(gè)例子中,我從模塊文件 sequence.js 中導(dǎo)出了一個(gè)函數(shù):
// in sequence.jsexport { sequence, toList, take };當(dāng)前模塊可以通過導(dǎo)入來使用其他模塊的函數(shù)或?qū)ο蟪伞?br />
import { sequence, toList, toList } from "./sequence";在某種程度上,我們可以認(rèn)為模塊是一個(gè)自動執(zhí)行的函數(shù),它將 import 的數(shù)據(jù)作為輸入,然后返回 export 的數(shù)據(jù)。
函數(shù)作用域
函數(shù)作用域意味著在函數(shù)中定義的參數(shù)和變量在函數(shù)內(nèi)的任何位置都可見,但是在函數(shù)外部不可見。
下面是一個(gè)自動執(zhí)行的函數(shù),被稱為IIFE。
(function autoexecute() {let x = 1;})();console.log(x);//Uncaught ReferenceError: x is not definedIIFE 的意思是立即調(diào)用函數(shù)表達(dá)式,是一個(gè)在定義后立即運(yùn)行的函數(shù)。
用 var 聲明的變量只有函數(shù)作用域。更重要的是,用 var 聲明的變量被提升到其作用域的頂部。通過這種方式,可以在聲明之前訪問它們。看看下面的代碼:
function doSomething(){console.log(x);var x = 1;}doSomething(); //undefined這種事不會發(fā)生在 let 中。用 let 聲明的變量只能在定義后訪問。
function doSomething(){console.log(x);let x = 1;}doSomething();//Uncaught ReferenceError: x is not defined
新聞熱點(diǎn)
疑難解答
圖片精選