提问者:小点点

从嵌套函数内部的外部函数返回,使用抛出


我有一个深深嵌套的函数塔里面的函数里面的函数等等,很深很深的里面,正好我找到了最外层的函数的结果。 我能找到的处理这种情况的最好方法(没有大量烦人的“超冗长的记账代码”)是“创造性地”(或者我应该说“不愉快地”?)使用抛/抓(throw/catch)。 像这样的东西:

function doStuff1(){}
function doStuff2(){}
...

function wrapper(){
    function first(){
        function second(){
            function third(){
                doStuff4();
                some loop {
                    var result = ...
                    if (something) throw result;
                }
            }
            while (lorem<ipsum){
                doStuff2();
                third();
                while (dolor<sit*amet){
                    doStuff3();
                    third();
                }
            }
        }
        doStuff1();
        second();
    }
    try {
        first();
        return "not found";
    } catch(e){
        if (e instanceof Error){ throw(e); } else { return e; }
    }
}

这样做有什么不对吗? 有没有更好的办法? (!!!请克制!!!来自“Don't be a cray baby and just distrating your code”的回答,谢谢。)

注意这不是重复的。 其他看似相似的问题将问题与异步调用混杂在一起,这里没有任何异步。 这个相关的问题处理的是嵌套循环(用于等),而不是函数。


共3个答案

匿名用户

更好的方法是使用return(如果你不能完全重构塔)。 它明确了您正在做什么以及何时从中间函数返回值; 您可以通过查看这些函数来判断结果可能在哪里提供。 相反,使用throw在那些中间层中是不可见的; 它神奇地以一种为错误条件设计的方式绕过它们。

如果您不想那样做,我认为除了抛出之外,您没有合理的替代方案。 我曾想过要走生成器函数或类似的路线,但我认为这只会使事情更复杂,而不是更少。

使用return并没有明显地使示例代码复杂化,而且(在我看来)可以使您更清楚地了解正在发生的事情以及预期的结果。

function wrapper(){
    function first(){
        function second(){
            function third(){
                doStuff4();
                some loop {
                    var result = ...
                    if (something) return result;
                }
            }
            doStuff2();
            let result = third();
            if (result) {
                return result;
            }
            doStuff3();
            return third();
        }
        doStuff1();
        return second();
    }
    return first() || "not found";
}

(在上面,对result进行了真实性测试;如果合适,请替换其他内容。)

匿名用户

评论1:仅仅因为这有点不合常规,这绝对不是反对那样做的好理由--那样做太愚蠢了。

就像“不要使用标签”是愚蠢的一样(参见关于跳出嵌套循环的链接问题(+接受的答案))。

我问的是好的理由,不是愚蠢的理由。 这是非传统的,那只是愚蠢; 相反,以下情况可能会发生:废话废话,这并不傻; 说得通?

注释2:在Wolfram mathematica中,这样做并不是非常规的。 在这种语言中,没有“try”,只有“throw”和“catch”,这两个词是为打破循环而设计的。 你可以使用“catch”来捕获系统抛出的错误,或者捕获你自己抛出的错误,以打破一个循环。 我发现,在这方面,Wolfram mathematica显然比JavaScript具有更好(更简单)的设计。 JavaScript不是世界上唯一的语言,也不是教皇写的,或者类似的东西。 把“JavaScript就是这样设计的”作为唯一的理由,你看,这正是我所说的愚蠢之处。

匿名用户

我认为你应该使用数组;

const funcs = [first, second, third];
for(let i = 0; i < funcs.length; ++i){
 const result = funcs[i]();
 if (result) break;
}

只应从具有结果的函数返回