闭包内的变量的继承是在定义闭包还是执行闭包函数时检查的?

2020-03-27 17:37:43 +08:00
 crella

闭包内的变量的继承是在定义闭包还是执行闭包函数时检查的?

下面比较了 c#、golang 、javascript 、php5 、python3 、ruby 的闭包或 lambda 。主要思路是写好闭包,再定义变量 y,其中闭包内用到 y 变量。

我的总结是:python3 、javascript 都是在执行时才检查闭包内变量,而 c#、golang 、php5 、ruby 都是在定义时已检查闭包内变量的。注意 golang 是编译型语言,c#是解释型语言(??)。

我是"hello world"水平,写错了轻拍,欢迎指正。php5 的闭包我不是很懂,照抄例子的,可能有错。

我本来是希望 ruby 的闭包可以像 python3 那样在执行闭包时再检查闭包内的变量的,查了一下其他语言才发现不统一的情况有点多。

以下是代码。


// c# 闭包 编译错误,在指定 f()时不存在 y

using System;
public class Test {
    delegate int Func();
    public static void Main() {
        int x = 1;
        Func f = () =>  (x+y);
        int y = 2;
        Console.WriteLine(f());
    }
}


// golang 闭包,编译错误,在指定 f()时不存在 y


package main
import "fmt"
func main () {
   var x int = 1
   f := func() int { return (x+y)}
   var y int = 2
   result := f()
   fmt.Println(result)
}


 // javascript 闭包,找得到 y
var x = 1;
function f() {
  function g() {
    return (x+y);
  }
  return g;
}
var y = 2;
console.log(f()());

# php5 闭包,找不到$y
$x = 1;
$f = function() use ($x, $y) { return ($x + $y); };
$y = 2;
echo($f());

# python3 闭包 1,都能找到 y

x = 1
def f():
  def g():
    return (x+y)
  return g()

y = 2
print(f())

# python3 闭包 2

x = 1
lam = lambda : (x+y)
y = 2
print(lam())


# ruby 闭包 1 都找不到 y

x = 1
pr = Proc.new do
   (x+y)
end
y = 2
puts 'proc 定义完毕'
puts pr.call

# ruby 闭包 2

x = 1
lam = lambda { return (x+y) }
y = 2
puts lam.call

984 次点击
所在节点    程序员
1 条回复
Zhuzhuchenyan
2020-03-27 19:41:10 +08:00
那具体说下 JS 为何能运行吧,var 在声明变量并赋值的时候,其实会做两个步骤,在词法作用域最上方声明,以及在该赋值的时候赋值,具体来说,以下代码和你贴出的代码等价:

var x;
var y;
x = 1;

function f() {
function g() {
return (x+y);
}
return g;
}
y = 2;
console.log(f()());

所以代码在运行到 x+y 这一行时完全知道 y 存在于全局的词法作用域(也就是说可以在闭包封闭的词法作用域中被引用到)
这种编程方式一般不被推荐,配置 lint 规则后会给出 variable 'y' used before declaration (no-use-before-declare)的报错

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/656875

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX