我对块内变量的范围感到困惑.这有效:
f = 'new'
[1,2,3].each do |n| puts f * n end
#=> new newnew newnewnew
Run Code Online (Sandbox Code Playgroud)
但这不是:
[1,2,3].each do |n|
a ||=[]
a << n
end
a
#=>a does not exsit!
Run Code Online (Sandbox Code Playgroud)
为什么是这样?请为我提供一些关于这个主题的资源.
什么令人困惑?
在第一个片段f中创建然后each执行块,它可以看到自身之外的东西(称为封闭范围).所以它可以看到f.
在a块中创建的第二个片段中,其范围就是该块.在街区外,a不存在.
当您引用名称(a例如)时,ruby将从当前范围向外,查看名称的所有封闭范围.如果它在其中一个封闭范围内找到它,则使用与该名称关联的值.如果没有,它将返回到最本地范围并在那里创建名称.后续的名称查找将产生与该名称关联的值.
当块结束时,该范围内的名称将丢失(值不会丢失,只会丢失名称;当垃圾收集器看到没有更多名称(或任何内容)引用该值时,值将丢失,并且gc收集值以重用其内存).
当一个街区结束时,你会爬上一个楼梯台阶.由于您在下面的步骤中看不到任何名称,因此您之前执行的步骤上的所有名称都将丢失.
如果这对你有所帮助,那就这么想吧.如果没有,不要.
1 实际上你是第二步,因为你不在全球范围内,但要使用全局范围的名称,你必须在名称的开头使用$.所以在楼梯示例中,如果您要查找的名称在开头有一个$,则直接查看顶部步骤.如果没有,你看起来不那么远.然而,这有点不对,因为程序中的所有楼梯都会分享相同的顶级步骤,这是一个奇怪的想法.