2011-04-02 73 views
6

我讀過函數範圍內的變量可以在當前範圍內訪問,當功能腳本是點源。PowerShell的大師,請澄清函數中的變量範圍

這是真的嗎?這是非常奇怪的,我覺得不尋常...

我可以澄清這個原因。例如,my-f$my-f-var一些整數,假設2:

PS1> . .\my-f-script.ps1 
PS1> my-f 
PS1> $my-f-var 
2 

我預計$my-f-var不可訪問,因爲裏面的功能!有沒有辦法讓變量變成私人的,或者是一種不用點源代碼來調用函數的方法?

回答

14

函數內的變量對於該範圍而言是本地的,除非您點擊調用函數名稱。當你點源腳本,頂級腳本變量有效地導入到當前範圍與函數定義例如,沿着:

PS> '$scriptvar = 2; function my-f { ${my-f-var} = 2 }' > my-f-script.ps1 
PS> Remove-Variable scriptvar, my-f-var 
Remove-Variable : Cannot find a variable with name 'scriptvar'. 
Remove-Variable : Cannot find a variable with name 'my-f-var'. 
PS> . .\my-f-script.ps1 
PS> $scriptvar 
2 
PS> ${my-f-var} 
PS> 

注意,$ {我-F-VAR}未在規定本地範圍。然而,如果我「點」的函數,則其內容被在當前範圍例如運行的調用:

PS> . my-f 
PS> ${my-f-var} 
2 

在這種情況下,在該函數的變量集合中的電流(調用)範圍,因爲設定用於調用它的'點'。

還有一些要點:您可以使用Get-Variable -scope或更方便(如果不太靈活)的全局,腳本,本地和專用修改器訪問各種範圍的變量。當你在一個函數內部訪問一個變量被定義在更高範圍內的變量時,你可以很好地閱讀它。但是當你設置它的時候,PowerShell本質上會做一個變量的「copy-on-write」 - 從該函數向下創建一個新的拷貝(即它所調用的其他函數)。如果你真的想修改一個更高範圍的變量,你可以使用$ global:Foo或者$ script:Foo來修改這些範圍。

如果您想避免無意中使用定義在函數之外的變量,則local範圍將派上用場。另一位MVP在最後一次MVP峯會上提出了這個觀點,它似乎是這些「最佳實踐」技巧之一。這裏的情景:

PS> $foo = 'bad' 
PS> function testscope { $fooo = 'good'; "The value of `$fooo is $foo" } 
PS> testscope 
The value of $fooo is bad 

注意,在這種情況下,在函數內部使用的$foo是一個錯字,但巧合的是有由typo'd名稱的變量。這不是該功能的意圖,它不能正常工作,儘管在這種情況下很難看到。下面,我們可以使用local說明符來確保該函數僅在變量的本地範圍內查找。它不會因爲輸入錯誤而找到它,但至少現在可以更容易地發現錯誤。當你不希望某些變量是你的函數調用等功能可見

PS> function testscope { $fooo = 'good'; "The value of `$fooo is $local:foo" } 
PS> testscope 
The value of $fooo is 

private範圍是非常有用的。

+0

好的,這是有道理的!不知道函數可以是點源:)。然後,microsoft technet上的[about_scripts](http://technet.microsoft.com/en-us/library/dd819484.aspx#)我認爲不正確。閱讀SCRIPT SCOPE AND DOT SOURCING部分。那是對的嗎? – 2011-04-02 06:34:05

+2

從PowerShell提示符執行'man about_scopes'。這將是一個很好的幫助主題閱讀。 – 2011-04-02 06:35:33

+4

並使用'Set-StrictMode -v latest'可以幫助您避免意外地引用來自外部作用域的變量... – Jaykul 2011-04-02 19:46:01