为什么本地定义的变量可以从另一个函数中成功访问? [英] Why is a variable defined locally successfully accessible from within another function?
问题描述
见下面的代码.将两个文件放在同一目录中,然后从 PS ISE 运行 Form1.ps1
See code below. Put both files in the same directory and run Form1.ps1
from the PS ISE
如您所见,(本地)变量 $localVar
是在事件处理程序 $button2_Click
中定义的.因此,我假设 $localVar
不会/不可能存在于 $button2_Click
范围之外,范围由定义事件处理程序的大括号定义.
As you can see, the (local) variable $localVar
is defined in the event handler $button2_Click
. As such, I assumed $localVar
would not/could not exist outside the scope of $button2_Click
with scope defined by the braces that define the event handler.
但是,如您所见,我使用 $localVar
的内容在函数 fA
中加载 $textbox2.Text
.当您单击 Test
按钮时,两个文本框都会显示 $localVar
However, as you can see, I use the contents of $localVar
to load $textbox2.Text
in the function fA
. When you click the Test
button, both textboxes display the contents of $localVar
发生了什么事?为什么可以从 fA
中访问 $button2_Click
的 $localVar
?
What's going on? Why is $button2_Click
's $localVar
accessible from within fA
?
Form1.ps1
function fA
{
$textbox2.Text = $localVar
}
$button2_Click =
{
$localVar = "set in `$button2_Click"
$textbox1.Text = $localVar
fA
}
. (Join-Path $PSScriptRoot 'Form1.designer.ps1')
$textbox1.Text = ""
$Form1.ShowDialog()
Form1.designer.ps1
[void][System.Reflection.Assembly]::Load('System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a')
[void][System.Reflection.Assembly]::Load('System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089')
$Form1 = New-Object -TypeName System.Windows.Forms.Form
[System.Windows.Forms.Button]$button2 = $null
[System.Windows.Forms.TextBox]$textBox1 = $null
[System.Windows.Forms.TextBox]$textBox2 = $null
[System.Windows.Forms.Label]$label1 = $null
[System.Windows.Forms.Label]$label2 = $null
[System.Windows.Forms.Button]$button1 = $null
function InitializeComponent
{
$button2 = (New-Object -TypeName System.Windows.Forms.Button)
$textBox1 = (New-Object -TypeName System.Windows.Forms.TextBox)
$textBox2 = (New-Object -TypeName System.Windows.Forms.TextBox)
$label1 = (New-Object -TypeName System.Windows.Forms.Label)
$label2 = (New-Object -TypeName System.Windows.Forms.Label)
$Form1.SuspendLayout()
#
#button2
#
$button2.Location = (New-Object -TypeName System.Drawing.Point -ArgumentList @([System.Int32]148,[System.Int32]12))
$button2.Name = [System.String]'button2'
$button2.Size = (New-Object -TypeName System.Drawing.Size -ArgumentList @([System.Int32]77,[System.Int32]36))
$button2.TabIndex = [System.Int32]0
$button2.Text = [System.String]'Test'
$button2.UseVisualStyleBackColor = $true
$button2.add_Click($button2_Click)
#
#textBox1
#
$textBox1.Location = (New-Object -TypeName System.Drawing.Point -ArgumentList @([System.Int32]67,[System.Int32]69))
$textBox1.Name = [System.String]'textBox1'
$textBox1.Size = (New-Object -TypeName System.Drawing.Size -ArgumentList @([System.Int32]106,[System.Int32]20))
$textBox1.TabIndex = [System.Int32]1
#
#textBox2
#
$textBox2.Location = (New-Object -TypeName System.Drawing.Point -ArgumentList @([System.Int32]247,[System.Int32]69))
$textBox2.Name = [System.String]'textBox2'
$textBox2.Size = (New-Object -TypeName System.Drawing.Size -ArgumentList @([System.Int32]106,[System.Int32]20))
$textBox2.TabIndex = [System.Int32]2
#
#label1
#
$label1.AutoSize = $true
$label1.Location = (New-Object -TypeName System.Drawing.Point -ArgumentList @([System.Int32]12,[System.Int32]72))
$label1.Name = [System.String]'label1'
$label1.Size = (New-Object -TypeName System.Drawing.Size -ArgumentList @([System.Int32]47,[System.Int32]13))
$label1.TabIndex = [System.Int32]3
$label1.Text = [System.String]'textbox1'
#
#label2
#
$label2.AutoSize = $true
$label2.Location = (New-Object -TypeName System.Drawing.Point -ArgumentList @([System.Int32]194,[System.Int32]72))
$label2.Name = [System.String]'label2'
$label2.Size = (New-Object -TypeName System.Drawing.Size -ArgumentList @([System.Int32]47,[System.Int32]13))
$label2.TabIndex = [System.Int32]4
$label2.Text = [System.String]'textbox2'
#
#Form1
#
$Form1.ClientSize = (New-Object -TypeName System.Drawing.Size -ArgumentList @([System.Int32]374,[System.Int32]110))
$Form1.Controls.Add($label2)
$Form1.Controls.Add($label1)
$Form1.Controls.Add($textBox2)
$Form1.Controls.Add($textBox1)
$Form1.Controls.Add($button2)
$Form1.Name = [System.String]'Form1'
$Form1.ResumeLayout($false)
$Form1.PerformLayout()
Add-Member -InputObject $Form1 -Name base -Value $base -MemberType NoteProperty
Add-Member -InputObject $Form1 -Name button2 -Value $button2 -MemberType NoteProperty
Add-Member -InputObject $Form1 -Name textBox1 -Value $textBox1 -MemberType NoteProperty
Add-Member -InputObject $Form1 -Name textBox2 -Value $textBox2 -MemberType NoteProperty
Add-Member -InputObject $Form1 -Name label1 -Value $label1 -MemberType NoteProperty
Add-Member -InputObject $Form1 -Name label2 -Value $label2 -MemberType NoteProperty
Add-Member -InputObject $Form1 -Name button1 -Value $button1 -MemberType NoteProperty
}
. InitializeComponent
推荐答案
函数 fA
看到你的变量,因为它运行在脚本块的 child 范围内,其中$localVar
已创建 - 这是一般 PowerShell 行为,并非特定于 ISE.
Function fA
sees your variable, because it runs in a child scope of the script block in which $localVar
was created - this is general PowerShell behavior, and not specific to the ISE.
当你创建一个带有 $localVar = ...
的变量时,它是 local 在以下意义上的:强>
When you create a variable with $localVar = ...
, it is local in the following sense:
可见且可直接修改在同一范围内,但不在任何父范围内.
visible and directly modifiable in the same scope, but not in any parent scopes.
可见在所有子作用域中,但不能在那里直接修改.
visible in all child scopes, but not directly modifiable there.
警告:从 模块 在一个单独的范围域(又名会话(子)状态)中运行,它只共享全局 范围作为祖先,代码在模块之外和其他模块中运行.因此,如果调用者在非模块代码中(全局范围除外)或来自不同模块,则从函数导入的模块不会看到其调用者的变量(以及函数和别名).
另一种说法:从模块导入的函数确实不在非模块调用者的子范围内(在全局范围之外)运行,因此不会看不到调用者的定义.
Caveat: Functions imported from modules run in a separate scope domain (a.k.a. session (sub)state) that only shares the global scope as an ancestor with code running outside of modules and in other modules. Therefore, a module imported from a function does not see its caller's variables (and functions and aliases), if the caller is in non-module code (other than the global scope) or from a different module.
Another way of putting it: a function imported from a module does not run in a child scope of a non-module caller (outside the global scope), and therefore doesn't see that caller's definitions.
您可以使用 $private:
范围修饰符来防止子范围看到变量.
You can use the $private:
scope modifier to prevent child scopes from seeing a variable.
如果您分配给最初在 parent 范围内创建的变量(仅按名称),(例如,$localVar = ...代码>),您将改为在 当前 范围内创建一个 新 局部变量
,它隐藏原始变量.
If you assign to a variable (by name only) that was originally created in a parent scope, (e.g., $localVar = ...
), you'll instead create a new, local variable, in the current scope, which shadows the original variable.
- 可以修改父作用域的变量,但您需要使用
Set-Variable -Scope
或作用域修饰符,例如$script:
(见下面的链接).
- It is possible to modify a parent scope's variables, but you need to use either
Set-Variable -Scope
or a scope modifier such as$script:
(see links below).
有关详细信息,请参阅:
For more information, see:
这个答案的最后一部分,提供了一个简洁的摘要.
the last section of this answer, which provides a concise summary.
这篇关于为什么本地定义的变量可以从另一个函数中成功访问?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!