Variable scoping in PowerShell

mathk picture mathk · Feb 17, 2012 · Viewed 122.3k times · Source

A sad thing about PowerShell is that function and scriptblocks are dynamically scoped.

But there is another thing that surprised me is that variables behave as a copy-on-write within an inner scope.

$array=@("g")
function foo()
{
    $array += "h"
    Write-Host $array
}

& {
    $array +="s"
    Write-Host $array
}
foo

Write-Host $array

The output is:

g s
g h
g

Which makes dynamic scoping a little bit less painful. But how do I avoid the copy-on-write?

Answer

Anton picture Anton · Mar 3, 2013

The PowerShell scopes article (about_Scopes) is nice, but too verbose, so this is quotation from my article:

In general, PowerShell scopes are like .NET scopes. They are:

  • Global is public
  • Script is internal
  • Private is private
  • Local is current stack level
  • Numbered scopes are from 0..N where each step is up to stack level (and 0 is Local)

Here is simple example, which describes usage and effects of scopes:

$test = 'Global Scope'
Function Foo {
    $test = 'Function Scope'
    Write-Host $Global:test                                  # Global Scope
    Write-Host $Local:test                                   # Function Scope
    Write-Host $test                                         # Function Scope
    Write-Host (Get-Variable -Name test -ValueOnly -Scope 0) # Function Scope
    Write-Host (Get-Variable -Name test -ValueOnly -Scope 1) # Global Scope
}
Foo

As you can see, you can use $Global:test like syntax only with named scopes, $0:test will be always $null.