代码之家  ›  专栏  ›  技术社区  ›  umar

使用闭包解决的自然问题

  •  2
  • umar  · 技术社区  · 16 年前

    例如,向一个人解释递归的一种自然方法可以是解释n!的计算!。理解像用递归计算数字的阶乘这样的问题是很自然的。类似地,通过读取每个元素并与所讨论的数字进行比较,在未排序的数组中找到一个元素几乎是轻而易举的事。另外,在另一个层次上,进行面向对象编程也是有意义的。

    8 回复  |  直到 16 年前
        1
  •  1
  •   David Hedlund    16 年前

    好吧,假设你正在用javascript生成一个菜单。

    var menuItems = [
       { id: 1, text: 'Home' },
       { id: 2, text: 'About' },
       { id: 3, text: 'Contact' }
    ];
    

    你在一个循环中创建它们,就像这样:

    for(var i = 0; i < menuItems.length; i++) {
    
        var menuItem = menuItems[i];
    
        var a = document.createElement('a');
        a.href = '#';
        a.innerHTML = menuItem.text;
    
        // assign onclick listener
    
        myMenu.appendChild(a);
    
    }
    

    现在,对于onclick侦听器,您可以尝试以下操作:

    a.addEventListener('click', function() {
        alert( menuItem.id );
    }, false);
    

    但您会发现,这将有每个链接警报“3”。因为在单击时,执行onclick代码,并且 menuItem 计算到最后一个项,因为这是在for循环的最后一次迭代时最后分配给它的值。

    相反,您可以做的是使用 菜单项 事实上 在执行的时候

    a.addEventListener('click', (function(item) {
        return function() {
            alert( item.id );
        }
    })( menuItem ), false);
    

    这是怎么回事?我们实际上是在创建一个接受 item 然后 立即 调用该函数,传递 . 所以“包装器”函数不是当你点击链接时要执行的。我们马上执行,并分配 返回 用作单击处理程序。

    这里发生的事情是,对于每个迭代,都会用一个新值调用函数 菜单项

    希望能把事情弄清楚=)

        2
  •  3
  •   Amadan    16 年前

    回调就是一个很好的例子。让我们看看JavaScript。

    想象一下,你有一个新闻网站,每个网站旁边都有标题、简短的广告语和“阅读更多…”按钮。当用户单击按钮时,您希望异步加载与所单击的按钮对应的内容,并在所请求的标题旁边向用户显示一个指示符,以便用户可以“看到正在处理的页面”。

    function handleClickOnReadMore(element) {
      // the user clicked on one of our 17 "request more info" buttons.
      // we'll put a whirly gif next to the clicked one so the user knows
      // what he's waiting for...
      spinner = makeSpinnerNextTo(element);
    
      // now get the data from the server
      performAJAXRequest('http://example.com/',
          function(response) {
            handleResponse(response);
    
            // this is where the closure comes in
            // the identity of the spinner did not
            // go through the response, but the handler
            // still knows it, even seconds later,
            // because the closure remembers it.
            stopSpinner(spinner);
          }
      );
    }
    
        3
  •  2
  •   Julian de Wit    16 年前

    排序例程 当我有物品清单的时候。
    通常有sort函数和一个单独的函数来比较这两个对象。
    现在你可以用一句话来表达

    List<Person> fList = new List<Person>();
    fList.Sort((a, b) => a.Age.CompareTo(b.Age));
    
        4
  •  2
  •   George    16 年前

    好吧,过了一段时间,和 Scala ,我无法想象一个代码,在一些没有闭包的列表上操作。例子:

    val multiplier = (i:Int) => i * 2
    val list1 = List(1, 2, 3, 4, 5) map multiplier
    
    val divider = (i:Int) => i / 2
    val list2 = List(1, 2, 3, 4, 5) map divider
    
    val map = list1 zip list2
    
    println(map)
    

    List((2,0), (4,1), (6,1), (8,2), (10,2))
    

    我不确定,如果这是一个例子,你正在寻找,但我个人认为,最好的例子闭包的真正力量可以看到名单的例子:各种排序,搜索,迭代等。

        5
  •  2
  •   Community Mohan Dere    9 年前

    我个人认为斯图尔特·兰里奇关于 Closures in JavaScript (幻灯片) pdf ). 它充满了好的例子和幽默感以及一点。

    alt text

        6
  •  1
  •   Marcelo Cantos    16 年前

    在C#中,函数可以实现通过接近点进行过滤的概念:

    IEnumerable<Point> WithinRadius(this IEnumerable<Point> points, Point c, double r)
    {
        return points.Where(p => (p - c).Length <= r);
    }
    

        7
  •  1
  •   Zorf    16 年前

    嗯,我每天都使用闭包,形式是函数组合运算符和curry运算符,它们都是通过闭包在Scheme中实现的:

    方案中的快速排序,例如:

    (define (qsort lst cmp)
      (if (null? lst) lst
          (let* ((pivot (car lst))
                 (stacks (split-by (cdr lst) (curry cmp pivot))))
            (append (qsort (cadr stacks) cmp)
                    (cons pivot
                          (qsort (car stacks) cmp))))))
    

    其中I cmp是一个二进制函数,通常用作(cmp one two),在本例中,我通过创建一个幺正谓词(如果您愿意)将堆栈一分为二,我的curry运算符:

    (define (curry f . args)
      (lambda lst (apply f (append args lst))))
    
    (define (curryl f . args)
      (lambda lst (apply f (append lst args))))
    

        8
  •  1
  •   Community Mohan Dere    9 年前

    闭包是JavaScript的强大功能之一,因为JavaScript是lambda语言。有关此主题的更多信息,请访问:
    Trying to simplify some Javascript with closures