JavaScript變量的作用域全解析
變量作用域是程序中定義這個變量的區(qū)域。
先來看一段示例:
/* 代碼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中處處有定義;而函數(shù)內(nèi)部聲明的變量是局部(local)變量,其作用域是局部性的,只在函數(shù)體內(nèi)部有定義。對于下面的輸出讀者應(yīng)不會感到意外。
/* 代碼2 */
var scope = "global"; function checkScope() { var scope = "local"; document.write(scope); } checkScope(); //輸出"local" document.write(scope); //輸出"global"
全局變量作用域中使用變量可以不用var語句,但在聲明局部變量是一定要使用var語句,否則會視為對全局變量的引用??聪旅娲a:
/* 代碼3 */
var scope = "global"; function checkScope() { scope = "local"; document.write(scope); } checkScope(); //輸出"local" document.write(scope); //輸出"local"
沒有塊作用域
Javascript沒有塊級作用域,函數(shù)中聲明的變量在整個函數(shù)中都是有定義的。對于下面的代碼對于生疏的讀者可能頗感意外:
/* 代碼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函數(shù)作用域內(nèi)都有效,因此在語句4.2(document.write(scope); )執(zhí)行的時scope引用的是局部變量,而此時局部變量scope尚未定義,所以輸出”undefined”。因此一個好的編程習(xí)慣是將所有的變量聲明集中起來放在函數(shù)的開頭。
在了解了上述內(nèi)容之后,讀者再看看代碼1應(yīng)該不會感到困惑了。
對象的屬性變量
對象的屬性變量比較容易理解,看一下下面的代碼讀者應(yīng)該不會感到疑惑。
/* 代碼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 作用域,調(diào)試代碼的時候可能會比較困難。
在函數(shù)中,如果用var來聲明一個變量,那么該變量的作用域就只限于該函數(shù)內(nèi)部,函數(shù)外的代碼無法訪問該變量。如果在該函數(shù)中再聲明一個函數(shù),那么這個內(nèi)部的函數(shù)也可以訪問這個變量。
反過來,如果聲明變量的時候沒有用var,那么此變量的作用域就不局限于這個函數(shù)了。JavaScript 引擎會再全局范圍中檢查該變量是否被定義過。如果該變量沒有被定義過,那么它就會被定義為一個全局變量。
函數(shù)可以訪問相同作用域中的變量:
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'
函數(shù)定以后可以看到函數(shù)內(nèi)變量值的改變:
var myFunction = function() { var foo = 'hello'; var myFn = function() { console.log(foo); }; foo = 'world'; return myFn; }; var f = myFunction(); f(); // logs 'world' -- haha
作用域也會穿越 — 閉包
// 一個自執(zhí)行的匿名函數(shù) (function() { var baz = 1; var bim = function() { alert(baz); }; bar = function() { alert(baz); }; })(); console.log(baz); // 在函數(shù)外面不能訪問 baz bar(); // 聲明 bar 的時候并沒有用 var // 所以 bar 是一個全局變量; 但是, // bar 和 baz 在相同的作用域內(nèi)被定義, // 所以 bar 可以訪問 baz // 其實(shí) bar 是個閉包函數(shù) bim(); // bim 的作用域只限于匿名函數(shù)內(nèi)部, // 所以這里不能調(diào)用
綜合
所謂作用域,就是說這個變量在代碼塊中的有效范圍。如果不理解 JavaScript 作用域,調(diào)試代碼的時候可能會比較困難。
在函數(shù)中,如果用var來聲明一個變量,那么該變量的作用域就只限于該函數(shù)內(nèi)部,函數(shù)外的代碼無法訪問該變量。如果在該函數(shù)中再聲明一個函數(shù),那么這個內(nèi)部的函數(shù)也可以訪問這個變量。
反過來,如果聲明變量的時候沒有用var,那么此變量的作用域就不局限于這個函數(shù)了。JavaScript 引擎會再全局范圍中檢查該變量是否被定義過。如果該變量沒有被定義過,那么它就會被定義為一個全局變量。
函數(shù)可以訪問相同作用域中的變量:
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'
函數(shù)定以后可以看到函數(shù)內(nèi)變量值的改變:
var myFunction = function() { var foo = 'hello'; var myFn = function() { console.log(foo); }; foo = 'world'; return myFn; }; var f = myFunction(); f(); // logs 'world' -- haha
作用域也會穿越 — 閉包
// 一個自執(zhí)行的匿名函數(shù) (function() { var baz = 1; var bim = function() { alert(baz); }; bar = function() { alert(baz); }; })(); console.log(baz); // 在函數(shù)外面不能訪問 baz bar(); // 聲明 bar 的時候并沒有用 var // 所以 bar 是一個全局變量; 但是, // bar 和 baz 在相同的作用域內(nèi)被定義, // 所以 bar 可以訪問 baz // 其實(shí) bar 是個閉包函數(shù) bim(); // bim 的作用域只限于匿名函數(shù)內(nèi)部, // 所以這里不能調(diào)用
- JavaScript高級程序設(shè)計之變量與作用域
- JS中作用域以及變量范圍分析
- JavaScript變量作用域及內(nèi)存問題實(shí)例分析
- JS塊級作用域和私有變量實(shí)例分析
- JavaScript變量類型以及變量作用域詳解
- javascript 的變量、作用域和內(nèi)存問題
- JS變量及其作用域
- js 作用域和變量詳解
- 關(guān)于JS變量和作用域詳解
- JavaScript 變量、作用域及內(nèi)存
- JavaScript中的變量作用域介紹
- js變量、作用域及內(nèi)存詳解
- 深入解析JavaScript中的變量作用域
- Javascript變量作用域詳解
- JavaScript中變量的作用域詳解
相關(guān)文章
THREE.JS入門教程(5)你應(yīng)當(dāng)知道的十件事
Three.js是一個偉大的開源WebGL庫,WebGL允許JavaScript操作GPU,在瀏覽器端實(shí)現(xiàn)真正意義的3D,本文會讓你了解一下使用THREE.JS處理3D/避免SetInterval/使用倒序循環(huán)等等,感興趣的朋友可以了解下哦2013-01-01如何用ajax來創(chuàng)建一個XMLHttpRequest對象
如何創(chuàng)建ajax代理對象? 我知道怎么做~就是不清楚怎么用語言表達(dá)?本文將詳細(xì)介紹如何解決此問題2012-12-12深入學(xué)習(xí)JavaScript中的Rest參數(shù)和參數(shù)默認(rèn)值
這篇文章主要介紹了深入學(xué)習(xí)JavaScript中的Rest參數(shù)和參數(shù)默認(rèn)值,是JS入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下2015-07-07