2011-04-02 27 views
6

Leo que las variables dentro del alcance de una función son accesibles en el ámbito actual cuando el script de función tiene una fuente de puntos.gurús de Powershell, aclare el ámbito variable en la función

¿Es verdad? Es muy extraño, e inusual, creo ...

Me pueden aclarar las razones de esto. Ejemplo, my-f conjuntos $my-f-var a algún entero, digamos 2:

PS1> . .\my-f-script.ps1 
PS1> my-f 
PS1> $my-f-var 
2 

Yo esperaría que $my-f-var no es accesible porque dentro de la función! ¿Hay alguna manera de hacer que las variables sean privadas, o una forma de llamar a la función sin dot-sourcing de su script?

Respuesta

14

Las variables dentro de la función son locales a ese alcance a menos que salpique la invocación del nombre de la función. Cuando se salpican la fuente de un guión, las variables de proceso de nivel superior se importan de manera efectiva en el ámbito actual junto con la definición de funciones, por ejemplo:

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> 

Tenga en cuenta que $ {my-f-var} no está definido en el alcance local. Sin embargo, si i 'punto' la invocación de la función a continuación, su contenido se ejecutan en el ámbito actual por ejemplo:

PS> . my-f 
PS> ${my-f-var} 
2 

En este caso, la variable establecida en la función se establece en el ámbito actual (invocando) porque del 'punto' utilizado para invocarlo.

Un par de puntos más: puede acceder a variables en varios ámbitos utilizando Get-Variable -scope o los modificadores globales, de script, locales y privados más convenientes (aunque menos flexibles). Cuando accede a una variable dentro de una función donde la variable se define en un ámbito superior, puede leerla perfectamente. Pero cuando lo configura, PowerShell esencialmente realiza una "copia por escritura" de la variable, creando una nueva copia con un alcance desde esa función hacia abajo (es decir, a las otras funciones a las que llama). Si realmente desea modificar una variable de mayor alcance, puede usar $ global: Foo o $ script: Foo para modificar en esos ámbitos.

El osciloscopio local es útil si quiere evitar inadvertidamente el uso de una variable definida fuera de su función. Otro MVP lo mencionó en la última cumbre de MVP y parece ser uno de esos consejos de "mejores prácticas". Este es el escenario:

PS> $foo = 'bad' 
PS> function testscope { $fooo = 'good'; "The value of `$fooo is $foo" } 
PS> testscope 
The value of $fooo is bad 

Tenga en cuenta que en este caso el uso de $foo dentro de la función es un error tipográfico, pero casualmente hay una variable con ese nombre typo'd. Esta no era la intención de la función y no está funcionando correctamente, aunque es difícil de ver en este caso. A continuación, podemos usar el especificador local para asegurarnos de que la función solo se ve dentro del alcance local de la variable. No lo encuentra debido al error tipográfico, pero al menos el error es un poco más fácil de detectar ahora.

PS> function testscope { $fooo = 'good'; "The value of `$fooo is $local:foo" } 
PS> testscope 
The value of $fooo is 

El alcance private es útil cuando no desea que ciertas variables sean visibles a las otras funciones que llama a su función.

+0

bien, ¡eso tiene sentido! No sabía que las funciones pueden ser dot-source :). Entonces el [about_scripts] (http://technet.microsoft.com/en-us/library/dd819484.aspx#) en Microsoft TechNet no es correcto, creo. Lea la sección ÁMBITO DE ESCRITURA Y FUENTE DE PUNTOS. ¿Es eso correcto? –

+2

Ejecute 'man about_scopes' desde el indicador de PowerShell. Ese sería un buen tema de ayuda para leer. –

+4

Y usar 'Set-StrictMode -v latest' puede ayudarlo a evitar referencias accidentales a variables del alcance externo ... – Jaykul

Cuestiones relacionadas