当前位置:  开发笔记 > 编程语言 > 正文

Javascript回调函数和递归

如何解决《Javascript回调函数和递归》经验,为你挑选了2个好方法。

这是一个脑力激荡问题,因为代码完全正常,它只会轻微刺激我的审美意识.我正在转向Stack Overflow,因为我自己的大脑现在正在让我失望.

这是一段代码,使用Google Maps JS API查找地址并在地图上放置标记.但是,有时初始查找失败,所以我想用不同的地址重复该过程.

geocoder.getLatLng(item.mapstring, function(point) {
    if (!point) {
        geocoder.getLatLng(item.backup_mapstring, function(point) {
            if (!point) return;
            map.setCenter(point, 13);
            map.setZoom(7);
            map.addOverlay(new GMarker(point));
        })
        return;
    }
    map.setCenter(point, 13);
    map.setZoom(7);
    map.addOverlay(new GMarker(point));
})

(第二个参数getLatLng是回调函数.)

当然,您可以看到中心和缩放地图并添加标记的三条线是重复的,一次在主回调中,一次在"后备回调"中(哈哈).你能找到一种方法来表达整个事物而没有任何冗余吗?如果您的解决方案适用于任意数量的备份地图字符串,您将获得奖励积分和我的奉承.



1> tway..:

其他答案都很好,但这里还有一个选择.这允许您保持与开始时相同的形式,但使用命名lambda函数的技巧,以便您可以递归地引用它:

mapstrings = ['mapstring1', 'mapstring2', 'mapstring3'];

geocoder.getLatLng(mapstrings.shift(), function lambda(point) {
   if(point) {
        // success
        map.setCenter(point, 13);
        map.setZoom(7);
        map.addOverlay(new GMarker(point));
    }
    else if(mapstrings.length > 0) {
        // Previous mapstring failed... try next mapstring
        geocoder.getLatLng(mapstrings.shift(), lambda);
    }
    else {
        // Take special action if no mapstring succeeds?
    }
})

第一次使用符号"lambda"时,它将它作为新的函数文字名称引入.第二次使用它时,它是一个递归引用.

函数文字命名在Chrome中有效,我认为它适用于大多数现代浏览器,但我没有测试它,我不知道旧浏览器.


尽管如此,文字命名比你的解决方案更清晰,更简洁
对于没有大量Javascript经验的人来说,那些arguments.callee的东西是非常明显的.这当然更易于维护.

2> 1800 INFORMA..:

有一种非常好的方法可以在不明确支持递归的语言结构中执行递归,称为定点组合器.最着名的是Y-Combinator.

以下是Javascript中一个参数函数的Y组合子:

function Y(le, a) {
    return function (f) {
        return f(f);
    }(function (f) {
        return le(function (x) {
            return f(f)(x);
        }, a);
    });
}

这看起来有点可怕,但你只需要写一次.使用它实际上非常简单.基本上,你将一个参数的原始lambda,并将其转换为两个参数的新函数 - 第一个参数现在是可以执行递归调用的实际lambda表达式,第二个参数是原始的第一个参数(point)你想要使用.

这是您在示例中使用它的方法.请注意,我使用的mapstrings是要查找的字符串列表,pop函数会破坏性地从头部删除元素.

geocoder.getLatLng(pop(mapstrings), Y(
  function(getLatLongCallback, point)
  {
    if (!point)
    {
      if (length(mapstrings) > 0)
        geocoder.getLatLng(pop(mapstrings), getLatLongCallback);
      return;
    }

    map.setCenter(point, 13);
    map.setZoom(7);
    map.addOverlay(new GMarker(point));
  });

推荐阅读
ar_wen2402851455
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有