作用域
在電腦程式設計中,作用域(scope,或譯作有效範圍)是名字(name)與實體(entity)的繫結(binding)保持有效的那部分電腦程式。不同的程式語言可能有不同的作用域和名字解析。而同一語言內也可能存在多種作用域,隨實體的類型變化而不同。作用域類別影響變數的繫結方式,根據語言使用靜態作用域還是動態作用域變數的取值可能會有不同的結果。
命名空間是一種作用域,使用作用域的封裝性質去邏輯上群組起關相的眾識別子於單一識別子之下。因此,作用域可以影響這些內容的名字解析。
歷史
編輯例子
編輯下列例子顯示了C++語言中多種不同的作用域聲明:
namespace N
{ // 命名空间作用域,仅是群组织别名
class C
{ // 类作用域,定义/声明成员变量和函数
void f (bool b)
{ // 函数作用域,包含可执行语句
if (b)
{ // 条件执行语句的无名作用域
...
}
}
};
}
靜態作用域與動態作用域
編輯靜態作用域又叫做詞法作用域,採用詞法作用域的變數叫詞法變數。詞法變數有一個在編譯時靜態確定的作用域。詞法變數的作用域可以是一個函數或一段代碼,該變數在這段代碼區域內可見(visibility);在這段區域以外該變數不可見(或無法訪問)。詞法作用域裏,取變數的值時,會檢查函數定義時的文字環境,捕捉函數定義時對該變數的繫結。
大多數現在程式語言都是採用靜態作用域規則,如C/C++、C#、Python、Java、JavaScript……
相反,採用動態作用域的變數叫做動態變數。只要程式正在執行定義了動態變數的代碼段,那麼在這段時間內,該變數一直存在;代碼段執行結束,該變數便消失。這意味着如果有個函數f
,裏面呼叫了函數g
,那麼在執行g
的時候,f
里的所有局部變數都會被g
訪問到。而在靜態作用域的情況下,g
不能訪問f
的變數。動態作用域裏,取變數的值時,會由內向外逐層檢查函數的呼叫鏈,並列印第一次遇到的那個繫結的值。顯然,最外層的繫結即是全域狀態下的那個值。
採用動態作用域的語言有Pascal、Emacs Lisp、Common Lisp(兼有靜態作用域)、Perl(兼有靜態作用域)。C/C++是靜態作用域語言,但在宏中用到的名字,也是動態作用域。