作用域(scope)指的是变量的可达性或可见性。不同类型的变量有不同的作用域规则。与self类似,作用域在程序的执行过程中也在不断的变化,也可以根据上下文推断出"谁在什么作用域中"。但是,self和作用域不是同一个东西,在self没有变化的时候,可以开始一个新的局部作用域,有时候,作用域和self一起改变。

全局作用域和全局变量:全局变量最不常用,但需要了解。全局变量用$开始,在整个程序的任何位置都可以访问,穿过所有的边界。

局部作用域:在任意时刻,程序都处在一个特定的局部作用域中。两个作用域的主要区别就是可访问的局部变量不同。

ruby中辨别作用域的开始和结束:

  • 顶层有它自己的局部作用域
  • 每一个类或模块定义块(class,module)有它自己的局部作用域,即使是嵌套的类/模块定义块也一样。
  • 每一个方法定义(def)有它自己的局部作用域

如下:

 class C
a = 1
def local_a
a = 2
p a
end
p a
end
C.new.local_a

输出1 2。

PS:每次使用关键字def,class,module引入一个定义块的时候,就开始了一个新的局部作用域。不论它们如何嵌套,都是这样的。这和c语言不一样,c语言中内部作用域可以看到外部作用域的变量,但是ruby中不能。

如下:

 class A
class B
a = 1
class C
a=2
p a
end
p a
end
end

输出2 1

局部作用域和self

当定义一个块的时候,就开始了新的局部作用域,也开始了一个特定的self的代码,但self和作用域并不是完全平行的起作用。

  • 同样的self,不同的局部变量。
class C
def a
a = 1
p self
p a
end
end
c = C.new
c.a
c.a

两次调用了c.a,其中的self是一样的,但是a却是不一样的变量。

  • 不同的self,同样的局部变量
 class A
p self
var = "hello"
p var
define_method :my_method do
p self
p var
end
end A.new.my_method

输出:

A
"hello"
#<A:0x1f08150>
"hello"

在这个函数里面,局部变量var是一样的,但是self却是不一样的,具体原因见下面的扁平化作用域。

常量的作用域和解析:

常量可定义在类或者模块里面,可以用相对路径或者绝对路径来访问。

 class A
X = 1
class B
Y = 2
class C
X = 3
end
p C::X
end
end
p A::X
p A::B::Y
p A::B::C::X

输出3 1 2 3

扁平化作用域:

在进入另一个作用域的时候,局部变量立刻失效,那么如何让局部变量能在新的作用域里使用呢?替换关键字就是一个方法。

  class 替换成Class.new

  module替换成Module.new

  def替换成Module#define_method

如下:

 var = "hello world"
class A
#在这里打印var
def method
#在这里打印var
end
end

假如想实现这个功能,让var能在这两个地方可见,可以用到扁平化作用域的知识。

如下:

 var = "hello world"
A = Class.new do
p var
define_method :method do
p var
end
end
A.new.method

输出两个hello world。

共享作用域:

假如你想在一组方法之间共享一个变量,但是有不希望其他方法可以访问这个变量,可以用到扁平作用域的方法

如下:

 def define_methods
shared = 0 Kernel.send :define_method,:counter do
shared
end Kernel.send :define_method,:inc do |x|
shared += x
end
end define_methods
p counter
inc(3)
p counter

输出0 3 。方法counter和inc之间会共享shared这个变量。

ruby中的作用域的更多相关文章

  1. 理解Ruby中的作用域

    作用域对于Ruby以及其它编程语言都是一个需要理解的至关重要的基础知识.在我刚开始学习ruby的时候遇到很多诸如变量未定义.变量没有正确赋值之类的问题,归根结底是因为自己对于ruby作用域的了解不够, ...

  2. 谈谈Ruby中的类变量

    Ruby中的类变量,很多文章都是不太建议使用的,主要原因在于他的一些特性容易导致犯一些错误,尤其在广泛使用元编程的时候. 初步接触类变量可能觉得他跟C++的类静态成员和Java中的静态变量没什么区别, ...

  3. ruby中的可调用对象--方法

    上一篇讲了ruby中的可调用对象proc和lambda,他们都是块转换成的对象.ruby中的可调用对象还有方法.通过使用method方法,并且以方法名作为参数(字符串或者符号),就可以得到一个方法对象 ...

  4. ruby中的可调用对象--proc和lamdba

    ruby中将块转变成对象的三种方法 ruby中的大部分东西都是对象,但是块不是.那么,如果你想存下来一个块,方便以后使用,你就需要一个对象.ruby中有三种方法,把块转换成可以利用的对象. Proc. ...

  5. Ruby 中的闭包-代码块

    看了一片文章https://ruby-china.org/topics/38385讲closure的. 写下一些感想: 闭包就是 一个函数能够记住和存取它的lexical作用域,即使这个函数是在它的l ...

  6. JavaScript中的作用域

    很多(JavaScript)开发者都在讨论"作用域",但它是什么?它们在JavaScript中的任何地方!我发现很多年轻的开发者不知道作用域是什么.他们中大多数人可以用jQuery ...

  7. [翻译]理解Ruby中的blocks,Procs和lambda

    原文出处:Understanding Ruby Blocks, Procs and Lambdas blocks,Procs和lambda(在编程领域被称为闭包)是Ruby中很强大的特性,也是最容易引 ...

  8. 探讨Nodejs中的作用域问题。

    在JS中有全局作用域和函数作用域,而在Nodejs中也自己的作用域,分为全局作用域(global)和模块作用域. js作用域: 以前学js的时候我们的全局对象是window,如: var a = 10 ...

  9. [No000010]Ruby 中一些百分号(%)的用法小结

    #Ruby 中一些百分号(%)的用法小结 #这篇文章主要介绍了Ruby 中一些百分号(%)的用法小结,需要的朋友可以参考下 what_frank_said = "Hello!"#% ...

随机推荐

  1. gradlew assembleRelease打包之前的配置

    http://blog.csdn.net/qq_15527709/article/details/70146061

  2. Asp.net中的Cache--HttpRuntim.Cache 和 HttpContext.Current.Cache

    在ASP.NET中有两个类都提供缓存支持, 一个是HttpRuntime类的Cache属性, 另一个是HttpContext类的Cache属性. 通过查看这两个属性的类型可以发现其实这两个属性都是Sy ...

  3. AWS系列-AWS EC2实例类型改配(机器配置升级)

    1.1 EC2实例升级需要先把升级的实例停机才能升级 1.2 如图选择需要升级的EC2,点击操作,实例设置,更改实例类型 1.3 选择你要想的配置,点击应用 1.4 启动EC2实例即可

  4. ecstore 修改后台搜索框搜索字段的排序顺序

    Ecstore后台要添加搜索字段,只需要在dbschema里写filtertype和filterdefault就行了,但要修改搜索字段的顺序要怎么弄呢?? 经测试,直接在dbschema文件里修改字段 ...

  5. U盘重装Windows系统

    1.制作一个U盘老毛桃或者大白菜 2.进入BIOS 3.Secure Boot-Disabled,作用是关闭微软的Secure BOOT,这个功能开启会导致不能识别U盘启动系统的安装 4.Lauch ...

  6. Linux网络流量控制工具—Netem

    第一篇:概念篇 Netem 是 Linux 2.6 及以上内核版本提供的一个网络模拟功能模块.该功能模块可以用来在性能良好的局域网中,模拟出复杂的互联网传输性能,诸如低带宽.传输延迟.丢包等等情况.使 ...

  7. git与sourceTree

    Window:http://my.oschina.net/lunqi/blog/500881?fromerr=bzaPk1Lx MAC:http://www.ithao123.cn/content-8 ...

  8. 【BZOJ2956】模积和 分块

    [BZOJ2956]模积和 Description 求∑∑((n mod i)*(m mod j))其中1<=i<=n,1<=j<=m,i≠j. Input 第一行两个数n,m ...

  9. Vue.js_构造器及其实例化概念

    Vue构造器 1.Vue.js是一个构造函数,编程中称之为构造器 2.每一个new Vue() 都是一个Vue构造函数的实例,这个过程叫做实例化 3.构造函数需要将其实例化后才会启用 var vm = ...

  10. [译]关于JavaScript 作用域你想知道的一切

    原文连接 在学习js的过程对闭包什么的,理解不好,偶然搜到这篇文章.豁然开朗,随翻译. Javacript 中有一系列作用域的概念.对于新的JS的开发人员无法理解这些概念,甚至一些经验丰富的开发者也未 ...