Переменные внутри функции являются локальными для этой области, если вы не ставите точку при вызове имени функции.Когда вы ставите исходный текст сценария, переменные сценария верхнего уровня эффективно импортируются в текущую область вместе с определениями функций, например:
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, по сути, выполняет «копирование при записи» переменной - создавая новую копию, ограниченную этой функцией и далее (т. Е. Для других функций, которые она вызывает).Если вы действительно хотите изменить переменную с более высокой областью действия, вы можете использовать $ 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
полезна, когда вы не хотите, чтобы определенные переменные были виднык другим функциям, которые вызывает ваша функция.