有什么方法可以判断javascript函数是否已经返回?

时间:2012-12-01 10:41:01

标签: javascript function return return-value undefined

我正在编写一些用于编写用户编写的JavaScript函数的代码,并且在逻辑中遇到了一个问题,如果所讨论的函数永远不会返回值{{1,那么我想触发特定行为永远不会评估关键字。

目前我假设如果一个函数返回return,它还没有返回,但是这不是严格正确的 - 因为函数总是undefined,或者返回一个值未定义的属性。

通过函数调用,您可以始终知道由于return undefined属性使用了多少参数,我想知道是否有人知道函数返回值的类似技巧?

那么,是否可以区分arguments.lengtha或甚至b

的返回值之间的差异
c

5 个答案:

答案 0 :(得分:4)

不,您无法可靠,跨浏览,通过仅使用return没有值或使用return undefined来判断函数是否仅通过其代码末尾返回。这由规范的Section 13.2.1涵盖。

这里的另一个答案表明你可以通过分析函数的源代码来实现它。但是,没有标准的机制可以做到这一点。虽然几乎所有的浏览器都可以从Function#toString中获得某种形式的源代码,但有些代码却没有(主要是移动浏览器),并且它没有被规范定义。但是如果你有一组你支持的浏览器,并且它们都拥有它,那将是你唯一真正的选择 - 但即使这样,你也不一定知道在函数中采用了哪个代码分支。

答案 1 :(得分:2)

将函数留空也将返回undefined,因此a,b和c都将返回相同的值。

实现这样的事情的唯一方法是在函数本身中实际设置某种标志,但我猜你希望能够独立于实际函数的实现来做这个。

答案 2 :(得分:2)

没有办法区分。

如果您真的想要,可以尝试分析函数的源代码并确定它是否有任何return语句,如果没有,则假设它不会返回值。当然,这有点难以确定函数是否有时返回而其他函数没有(例如,if-block中的return语句)

答案 3 :(得分:2)

这很疯狂,绝对不推荐,它会创建一个函数副本,修改函数体并使用eval

function returnProxy(func,args) {
    var returnFlag = Math.random()+"";

    // create new function based on passed function body
    var fullFuncBody = func.toString();
    var tmpFuncStr = "function  "+ fullFuncBody.substr(fullFuncBody.indexOf("("));

    tmpFuncStr = tmpFuncStr.substr(0,tmpFuncStr.length-1)+"\nreturn '"+returnFlag+"'}";

    var tmpFunc;
    eval("tmpFunc = "+tmpFuncStr); // really bad things

    var funcOut = tmpFunc.apply(this,args);

    return {
        out: (funcOut == returnFlag) ? undefined : funcOut,
        returned: (returnFlag != funcOut)
    }
}

假设你有这样的功能,

function someFunction(action) {
    switch(action) {
        case 1:
            return undefined;
        case 2:
            return "hello";
    }
}

你可以使用这样的代理功能:

returnProxy(someFunction,[1]); // instead of calling someFunction(1)

第一个参数是函数本身,第二个参数是参数数组

返回值将是一个具有2个属性的对象,out包含函数结果,returned是一个布尔值,表示函数是否返回

示例输出,

returnProxy(someFunction,[1]); // {out: undefined, returned: true}
returnProxy(someFunction,[2]); // {out: "hello", returned: true}
returnProxy(someFunction,[3]); // {out: undefined, returned: false} 

答案 4 :(得分:0)

您只能通过包装器调用函数,但我不确定这是否适合您的用例。

function invoker(f) {
    var actualFunc = f,
        invokeCount = 0;

    function invoke() {
        invokeCount = invokeCount +1;
        return actualFunc.apply(this, arguments);
    }

    function invoked() {
       return invokeCount;
    }

    return {
      invoke: invoke,
      invoked: invoked
    };
}

var a = function(){  };
var b = function(){ return undefined; };
var c = function(){ if(1){}else{return undefined;}; };

var ainvoker = new invoker(a);    

alert(ainvoker.invoke());
alert(ainvoker.invoked());