2011-04-02 59 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