如何使用回调更改方法局部变量?

时间:2014-07-10 05:24:09

标签: javascript ruby

var hello = function(callback) {
    var greet = "hello world";
    var name = "doug";
    callback();
    console.log(greet, name)
}

hello(function() {
    greet = "こにちわ";
    name = "だぐ";
    console.log(greet, name)

})
こにちわ だぐ
hello world doug 

是否可以覆盖闭包之外的局部变量并运行该范围内的其余函数?所以,我想要一个输出:

こにちわ だぐ
こにちわ だぐ

我意识到回调中的范围只是遮蔽外部作用域中的局部变量,但是有没有办法直接访问外部作用域并改变那里的变量?

Bonus,这在Ruby中是否可行?

修改 我能够这样做,有更好的方法吗?:

var hello = function(callback) {
    this.greet = "hello world";
    this.name = "doug";
    callback.call(this);
    console.log(greet, name)
}

hello(function() {
    this.greet = "こにちわ";
    this.name = "だぐ";
    console.log(this.greet, this.name)

})

2 个答案:

答案 0 :(得分:1)

您可以在Ruby中使用实例变量实现相同的功能,如下所示:

def hello(&block)
  @a = "Foo"
  @greet = "Hello"
  block.call
  puts "#{@greet}, #{@a}"
  end

 hello do
   @a = "Bar"
   @greet = "Hi"
  puts "#{@greet}, #{@a}"
 end

# => Hi, Bar
# => Hi, Bar

答案 1 :(得分:1)

使用Javascript:

我记得

this.var公平不是局部变量。由于我对Javascript的了解有限,我会说this.var的版本很好 根据您的需要,我建议只传递一个参数,例如var hello = function(var1)。你可以使用某种哈希:

var h = new Object()
h['greet'] = 'Hello'

红宝石:

bjhaid所述,您可以在代码中的某处使用实例变量(@a="new value")。

您可以使用全局变量($var)。没有新的类/对象,全局变量和实例变量非常相似:整个程序可以改变它 如果你正在创建新的类/对象,我建议坚持使用实例变量,因为只有类/对象可以改变它(当然没有像some_object.instance_variable_set :@a, '34'那样的元编程。)

我想你会在大多数情况下使用实例变量,但是我应该写其他方式,因为你的需求可能会有所不同。

  

如何使用回调更改方法局部变量?

如果你真的需要局部变量:

def meth1 &block # & - change block to the lambda
  a = 42
  b = 33
  block.call binding # "send" local scope (variables like `a`, `b`) to the block
  puts a,b
end

# `bin` is what you send in the `meth1` method; 
`eval` may change variables etc
meth1 {|bin| bin.eval 'a="str"'; bin.eval 'b=:FF' } 

您可以使用块中的隐式返回(您不能将returnproc类型的块一起使用;并且对方法的块发送将转换为{{1 }} type block)

proc

当然可以使用少数变量可以指向到一个对象的事实,例如字符串。如果修改该字符串,则指向该字符串的每个变量都将看到该更改。这就是所谓的修改,我记得很公平。

def meth2 &block
  a = 1
  b = 2
  a, b = block.call # returns array (in this case); equivalent: `arr=block.call; a=arr[0]; b=arr[1]`
  puts a,b
end

meth2 {[2,3]}

但是,这种方法是有限的。您可以就地修改字符串,数组,哈希,但不能修改符号或数字。在适当位置修改的方法可能在其名称的末尾有def meth3 &block a = "string a" b = "something b" block.call a, b puts a, b end meth3 do |a,b| a.gsub! 's', '*' b.gsub! 'b', '^' end (bang),但这不是规则。

注意:

这种方法很简单,可以说明如何做某事。我应该注意到: !几乎可以运行任何代码。它很危险(而且速度慢)所以请谨慎使用。您应该检查传递给eval

的字符串

阻止:如果你不发送阻止(例如只是呼叫eval),它将引发错误。您可能想要检查是否存在阻止 - method block_given? 您可以检查返回的块(在类似于meth3的情况下)。当块没有返回任何 good 时,您可以将变量更改为默认值。

适应性:我认为这很危险。您必须记住指向特定单元格的每个变量。