如何在Ruby中编写IIFE?

时间:2015-11-04 13:57:02

标签: javascript ruby idioms iife

在Javascript中,IIFE(即时调用函数表达式,尽管可能有其他扩展的缩写)可以写成:

(function () {
  var foo = 'bar'
  console.log('hi!');
})();

其中变量声明foo不会污染当前范围。我怎样才能在Ruby文件中做同样的事情?

我想在约束范围内创建一些临时变量(带闭包),并使文件中的其他代码无法访问它们。

2 个答案:

答案 0 :(得分:3)

defined?(foo)
# => nil

# This defines a lambda, i.e. a closure with its own variable scope, among other things
# and directly executes it
lambda {
  foo = 'bar'
  puts foo
}.()

defined?(foo)
# => nil

在这个例子中,我们首先检查是否定义了变量foo,而不是。然后,我们创建一个新的lambda对象(在Ruby中是一种特殊的Proc。并直接执行它。

Proc继承周围范围的变量,以便在proc中也可以访问(和更改)已定义的所有局部变量。但是,proc中定义的新变量只在proc之外不可见。

这可以通过最终的defined?声明进行验证。

请注意,这种技术不是很像红宝石。相反,您应该创建可以随后调用的实际方法。为了封装数据和行为,您还可以创建小类,即使是一次性使用,它也能完全处理您的行为和所有必需的数据。

通常在Ruby中,你倾向于不传递匿名闭包(即javascript中的匿名函数或Ruby中的procs / lambdas / blocks)但是使用完整对象。如果您经常在代码中使用上述技术,那么您将从经验丰富的ruby开发人员那里获得有关的一瞥。

答案 1 :(得分:2)

好吧,你也是这样做的:写一个任意的lambda文字,并立即调用它。

但有一点需要注意:Ruby没有变量声明。因此,在块内部也存在块内的变量名称的使用是指捕获的外部变量,而在ECMAScript中,如果在函数内声明void TabletWidget::mousePressEvent(QMouseEvent *event) { if (!_deviceActive) qDebug() << "mousePressEvent"; } ,它将遮蔽外部变量{{1} }。

如果你想在Ruby中使用相同的行为,你必须在块的参数列表中显式声明var foo作为块局部变量:

foo

如果不这样做,则块内的赋值将修改捕获的外部绑定。比较:

foo

如您所见,外部绑定已被修改。

-> (;foo) do
  foo = 'bar'
  puts 'hi!'
end.()

如您所见,只有第二个实际匹配ECMAScript版本:

foo = 'foo'

-> do
  foo = 'bar'
  puts 'hi!'
end.()

foo
# => 'bar'