Javascript 用 function 來當作一個 scope. 在 function 裡面再宣告一個 function 的話就會產生一個新的 scope. 我們來看看下面的範例吧.
function outer_scope(){ var a = 'I am `a` from outer scope', b = 'I am `b` from outer scope'; console.log( 'logging from outer scope before inner scope function declaration' ); console.log( 'a: ' + a ); console.log( 'b: ' + b ); console.log( '------------------------------------------' ); function inner_scope_1(){ console.log( 'logging from inside function inner_scope_1 before variable declaration' ); console.log( 'a: ' + a ); a = 'I will overwrite the outer scope `a`'; console.log( 'logging from inside function inner_scope_1 after variable declaration' ); console.log( 'a: ' + a ); console.log( '------------------------------------------' ); } function inner_scope_2(){ console.log( 'logging from inside function inner_scope_2 before variable declaration' ); console.log( 'b: ' + b ); var b = 'I will not overwrite the outer scope `b`'; console.log( 'logging from inside function inner_scope_2 after variable declaration' ); console.log( 'b: ' + b ); console.log( '------------------------------------------' ); } inner_scope_1(); inner_scope_2(); a = 'I will be the new `a`'; b = 'I will be the new `b`'; console.log( 'logging from outer scope after inner scope executed' ); console.log( 'a: ' + a ); console.log( 'b: ' + b ); console.log( '------------------------------------------' ); } outer_scope();
結果
logging from outer scope before inner scope function declaration a: I am `a` from outer scope b: I am `b` from outer scope ------------------------------------------ logging from inside function inner_scope_1 before variable declaration a: I am `a` from outer scope logging from inside function inner_scope_1 after variable declaration a: I will overwrite the outer scope `a` ------------------------------------------ logging from inside function inner_scope_2 before variable declaration b: undefined logging from inside function inner_scope_2 after variable declaration b: I will not overwrite the outer scope `b` ------------------------------------------ logging from outer scope after inner scope executed a: I will be the new `a` b: I will be the new `b` ------------------------------------------
從上面的結果可以清楚的看到在內層 scope 沒有用 var
宣告的變數會複寫掉外層 scope 的變數. 在內層裡用 var
開頭宣告的變數會變成 local 變數並只存在這一個 scope( function ) 裡面.
這也被叫做 closure
. 那我們又是在何時會用到以及如何使用 closure
呢? 在物件導向程式設計裡通常是用 class attributes 來儲存資料. 在 Javascript 用 closure 我們可以把資料存在上一層 scope 的變數裡以便跨 function 使用.
範例
function photo(){ var name = 'ben'; return{ say_my_name : function(){ console.log( name ); }, rename : function( new_name ){ name = new_name; } }; } var pic = new photo; pic.say_my_name(); pic.rename( 'bibi' ); pic.say_my_name();
結果
ben bibi
node.js function scope
node.js 有他處理 scope 的慣例. 在瀏覽器執行的 javascript, 在最上層 scope 用 var
宣告的變數就會是全域變數. 這就是為什麼我們常用 self executing anonymous function pattern 來避免全域函數.
在瀏覽器端的 javascript 下面的程式碼等於 window.name = 'ben'
var name = 'ben';
在 node.js 裡當它載入一個檔案或模組時會在外層包一層 executing anonymous function
var name = 'ben'; // the above equals to the following ( function( global ){ var name = 'ben'; })( global );
要讓變數成全域變數你必須要用 global
這個 keyword 來宣告
global.name = 'ben';
希望上面的範例能讓你清楚的了解什麼是 scope 以及如何使用 closure. 了解了之後接下來我們要來看看 javascript callbacks.