變數作用域是程式中定義這個變數的區域。
先來看一段範例:
/* 代碼1 */
var scope = "global "; function checkScope() { var scope = "local "; function childCheck() { var scope = "childLocal "; document.write(scope); } function childUndefined() { document.write(scope); var scope; } function childOverride() { scope = "childOverride "; document.write(scope); } document.write(scope); //输出"local" childCheck(); //输出"childLocal" childUndefined(); //输出"undefined" childOverride(); //输出"childOverride" document.write(scope); //输出"childOverride" } checkScope(); //输出"local childLocal undefinedchildOverride childOverride" document.write(scope); //输出"global "
全域作用域與局部作用域
全域(global)變數的作用域是全域的,在Javascript中處處有定義;而函數內部宣告的變數是局部(local)變數,其作用域是局部性的,只在函數體內部有定義。對於下面的輸出讀者應不會感到驚訝。
/* 代碼2 */
var scope = "global"; function checkScope() { var scope = "local"; document.write(scope); } checkScope(); //输出"local" document.write(scope); //输出"global"
全域變數作用域使用變數可以不用var語句,但在宣告局部變數是一定要使用var語句,否則會視為對全域變數的參考。看下面程式碼:
/* 代碼3 */
var scope = "global"; function checkScope() { scope = "local"; document.write(scope); } checkScope(); //输出"local" document.write(scope); //输出"local"
沒有塊作用域
Javascript沒有區塊級作用域,函數中宣告的變數在整個函數中都是有定義的。對於下面的程式碼對於生疏的讀者可能頗感意外:
/* 代碼4 */
var scope = "global"; function checkScope() { document.write(scope); //语句4.1 var scope = "local"; //语句4.2 document.write(scope); } checkScope(); //输出"undefinedlocal"
由於語句4.1(var scope = "local";)宣告的變數在整個checkScope函數作用域內都有效,因此在語句4.2(document.write(scope); )執行的時scope引用的是局部變數,而此時局部變數scope尚未定義,所以輸出」undefined」。因此一個好的程式設計習慣是將所有的變數宣告集中起來放在函數的開頭。
在了解了上述內容之後,讀者再看看程式碼1應該不會感到困惑了。
物件的屬性變數
物件的屬性變數比較容易理解,看一下下面的程式碼讀者應該不會感到疑惑。
/* 代碼5 */
var scope = "global "; var obj = new Object(); obj.scope = "object "; obj.checkScope = function () { var scope = "loacl "; document.write(scope); //输出"loacl" document.write(this.scope); //输出"object" document.write(window.scope); //输出"global" } obj.checkScope(); //输出"loacl object global"
所謂作用域,就是說這個變數在程式碼區塊中的有效範圍。如果不理解 JavaScript 作用域,調試程式碼的時候可能會比較困難。
在函數中,如果用var來宣告一個變量,那麼該變數的作用域就只限於該函數內部,函數外的程式碼無法存取該變數。如果在該函數中再宣告一個函數,那麼這個內部的函數也可以存取這個變數。
反過來,如果宣告變數的時候沒有用var,那麼此變數的作用域就不限於這個函數了。 JavaScript 引擎會再全域範圍檢查該變數是否被定義過。如果該變數沒有被定義過,那麼它就會被定義為一個全域變數。
函數可以存取相同作用域中的變數:
var foo = 'hello'; var sayHello = function() { console.log(foo); }; sayHello(); // logs 'hello' console.log(foo); // also logs 'hello'
變數作用域以外的程式碼不能存取該變數:
var sayHello = function() { var foo = 'hello'; console.log(foo); }; sayHello(); // logs 'hello' console.log(foo); // doesn't log anything
不用作用域中名稱相同的變量,有不同的值:
var foo = 'world'; var sayHello = function() { var foo = 'hello'; console.log(foo); }; sayHello(); // logs 'hello' console.log(foo); // logs 'world'
函數定以後可以看到函數內變數值的改變:
var myFunction = function() { var foo = 'hello'; var myFn = function() { console.log(foo); }; foo = 'world'; return myFn; }; var f = myFunction(); f(); // logs 'world' -- haha
作用域也會穿越 — 閉包
// 一个自执行的匿名函数 (function() { var baz = 1; var bim = function() { alert(baz); }; bar = function() { alert(baz); }; })(); console.log(baz); // 在函数外面不能访问 baz bar(); // 声明 bar 的时候并没有用 var // 所以 bar 是一个全局变量; 但是, // bar 和 baz 在相同的作用域内被定义, // 所以 bar 可以访问 baz // 其实 bar 是个闭包函数 bim(); // bim 的作用域只限于匿名函数内部, // 所以这里不能调用
綜合
所謂作用域,就是說這個變數在程式碼區塊中的有效範圍。如果不理解 JavaScript 作用域,調試程式碼的時候可能會比較困難。
在函數中,如果用var來宣告一個變量,那麼該變數的作用域就只限於該函數內部,函數外的程式碼無法存取該變數。如果在該函數中再宣告一個函數,那麼這個內部的函數也可以存取這個變數。
反過來,如果宣告變數的時候沒有用var,那麼此變數的作用域就不限於這個函數了。 JavaScript 引擎會再全域範圍檢查該變數是否被定義過。如果該變數沒有被定義過,那麼它就會被定義為一個全域變數。
函數可以存取相同作用域中的變數:
var foo = 'hello'; var sayHello = function() { console.log(foo); }; sayHello(); // logs 'hello' console.log(foo); // also logs 'hello'
變數作用域以外的程式碼不能存取該變數:
var sayHello = function() { var foo = 'hello'; console.log(foo); }; sayHello(); // logs 'hello' console.log(foo); // doesn't log anything
不用作用域中名稱相同的變量,有不同的值:
var foo = 'world'; var sayHello = function() { var foo = 'hello'; console.log(foo); }; sayHello(); // logs 'hello' console.log(foo); // logs 'world'
函數定以後可以看到函數內變數值的改變:
var myFunction = function() { var foo = 'hello'; var myFn = function() { console.log(foo); }; foo = 'world'; return myFn; }; var f = myFunction(); f(); // logs 'world' -- haha
作用域也會穿越 — 閉包
// 一个自执行的匿名函数 (function() { var baz = 1; var bim = function() { alert(baz); }; bar = function() { alert(baz); }; })(); console.log(baz); // 在函数外面不能访问 baz bar(); // 声明 bar 的时候并没有用 var // 所以 bar 是一个全局变量; 但是, // bar 和 baz 在相同的作用域内被定义, // 所以 bar 可以访问 baz // 其实 bar 是个闭包函数 bim(); // bim 的作用域只限于匿名函数内部, // 所以这里不能调用