我读到当函数脚本是点源时,函数范围内的变量可以在当前作用域中访问。
这是真的吗?这很奇怪,我觉得不寻常......
我可否澄清其原因。例如,my-f
将$my-f-var
设置为某个整数,假设为2:
PS1> . .\my-f-script.ps1
PS1> my-f
PS1> $my-f-var
2
我希望$my-f-var
无法访问,因为在函数内部!有没有办法让变量变为私有,或者在没有点源脚本的情况下调用函数的方法?
答案 0 :(得分: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>
请注意,$ {my-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
是一个拼写错误,但巧合的是,这个错字名称会有一个变量。这不是函数的意图,虽然在这种情况下很难看到,但它无法正常工作。下面,我们可以使用local
说明符来确保该函数仅在变量的局部范围内查找。由于拼写错误,它找不到它,但至少现在更容易发现错误。
PS> function testscope { $fooo = 'good'; "The value of `$fooo is $local:foo" }
PS> testscope
The value of $fooo is
当您不希望某些变量对您的函数调用的其他函数可见时,private
范围很有用。