闭包和 CoffeeScript 的作用域

Closures and CoffeeScript's Scoping

下面的代码定义了两个函数,linescircles,即return一个函数,分别是fg。函数 fg 相等(() -> size)只是为了简单起见,但通常它们是变量 size.

的不同函数
lines = () ->
    size = 10 # default value
    f = () -> size
    f.size = (_) ->
      size = _
      f
    f

circles = () ->
    size = 15 # default value
    g = () -> size
    g.size = (_) ->
      size = _
      g
    g

在控制台上,以上代码生成以下模式,这正是我需要的:

> lines()() # 10
> lines().size(20)() # 20
> circles()() # 15
> circles().size(30)() #30

您可能会注意到,f.sizeg.size 方法是闭包,它们在 linescircles 上是相同的。那么我的问题是:如何避免重复 size 方法的代码?(使用 coffeescript 或 javascript)

我尝试了不同的解决方案,但没有找到正确的方法。为了复制闭包,size 方法中的 size 变量应该引用 lines 第一行定义的 size 变量(同样适用于 circles).

你可以定义一个工厂函数来生产你的个人 "constructors":

shape = (defaultSize, calculate = (size) -> size) ->
    () ->
        size = defaultSize
        f = () -> calculate size
        f.size = (_) ->
            size = _
            f
        f

lines = shape(10)

circles = shape(15, (size) -> size * size * Math.PI)

编译为:

var circles, lines, shape;

shape = function(defaultSize, calculate) {
  if (calculate == null) {
    calculate = function(size) {
      return size;
    };
  }
  return function() {
    var f, size;
    size = defaultSize;
    f = function() {
      return calculate(size);
    };
    f.size = function(_) {
      size = _;
      return f;
    };
    return f;
  };
};

lines = shape(10);

circles = shape(15, function(size) {
  return size * size * Math.PI;
});

console.log(lines()());

console.log(lines().size(20)());

console.log(circles()());

console.log(circles().size(30)());

您不能在您的代码中使用辅助函数,因为它无法按预期访问闭包变量。但是,您可以将整个代码包装在一个函数中,以便它 returns 分别是 linescircles 函数:

make = (def, accessor) ->
    () ->
        size = def
        f = () -> accessor size
        f.size = (_) ->
           size = _
           f
        f

lines = make 10, (size) -> size
circles = make 15, (size) -> size