简体   繁体   中英

Is it optional to use the $global: scope prefix when referencing a global variable?

如果我使用$global:MyVariable = "123"声明并初始化一个 PowerShell 变量,那么我是否需要在任何我使用该变量的地方使用 $global: 还是可以只使用 $MyVariable?

  • In principle you can use just $MyVariable to reference the value of a global variable by that name , but you may see a different variable's value , situationally.

  • Specifically, if any intervening ancestral (parent) scope or even the calling scope itself has also created a $MyVariable variable (which typically happens implicitly by simple assigmnent ; eg, $MyVariable = ... ), you will see that variable's value instead.

  • You're only guaranteed to see the global value if you do use the global scope specifier, namely: $global:MyVariable (or Get-Variable -ValueOnly -Scope Global MyVariable ) [1]

  • By default, variables are visible , but not directly modifiable in all descendant (child) scopes.

    • Therefore you must use $global:MyVariable / Set-Variable -Scope Global in order to modify (set) a global variable ; without $global: you'll implicitly create a local variable by the same name.
    • For more on PowerShell's scoping rules, see the last section of this answer .

[1] In real-world scenarios, even code in PowerShell modules sees global variables with scope specifier $global: , and the implicit visibility of global variables always applies.

For in-memory modules, there is a way to make $global / -Scope global refer to a different scope , namely the module's own top-level scope, but the technique is obscure, not documented, and its real-world utility is unknown.
Read on, if you want to know more.


Optional reading : Creating an in-memory module that sees its own top-level scope as the global scope:

PetSerAl has discovered a little-known way to create an in-memory module in a manner that makes it see $global: / -Scope global as its own top-level scope rather than the true global scope - curiously, not using an explicit scope reference makes the code still see (non-shadowed) global variables:

$global:MyVariable = 42 # Create a true global variable.

# Create an in-memory module for which its *own top-level scope*
# becomes the "global" scope, by virtue of passing $false to the
# [psmoduleinfo] constructor:
& ([psmoduleinfo]::new($false)) {
  @"
   "$global:MyVariable",
   "$(Get-Variable -ValueOnly -Scope global MyVariable)",
   "$MyVariable"
"@
}

yields:

Get-Variable : Cannot find a variable with the name 'MyVariable'.
# ...

   "",  # $global:MyVariable didn't find the variable
   ",   # Neither did Get-Variable -Scope Global (see error above)
   "42" # OK - implicit visibility of true global variables

Note that neither New-Module nor Import-Module (for persisted modules) offer this functionality.

The obscure & <module-info> { ... } technique used above for invoking a script block in a module's scope is explained in this excellent blog post by Patrick Meinecke .

Run this and see that it is best to always specify, if you don't you will not alwys get what you might expect

function func {
    "0. $myvar"
    $myvar='funclocal'
    "1. $myvar"
    "2. $Global:myvar"
}
$Global:myvar='global'
func
"3. $Global:myvar"

你不需要使用 $global: 调用时

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM