2

return私は現在、ユーザーが作成したJavaScript関数をラッパーするコードを作成していますが、問題の関数が値を返さない場合、つまりキーワードが評価されない場合に、特定の動作をトリガーしたいというロジックのポイントに遭遇しました。

現在、関数がを返す場合、それは返されないと想定していますがundefined、これは厳密には当てはまりません。関数は常にreturn undefined、または未定義のプロパティの値を返すことができるためです。

関数呼び出しを使用すると、プロパティのために使用されたパラメーターの数を常に知ることができますarguments.length。関数の戻り値について同様のトリックを知っている人はいないでしょうか。

それで、の戻り値の違いを知ることは可能ですかabあるいはc

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

5 に答える 5

4

いいえ、クロスブラウザで、関数がコードの最後に到達しただけで返されるのか、return値なしで使用するのか、を使用するのかを確実に判断することはできませんreturn undefined。これは、仕様のセクション13.2.1でカバーされています。

ここでの別の答えは、関数のソースコードを分析することでそれができることを示唆しています。ただし、それを行うための標準的なメカニズムはありません。ほぼすべてのブラウザが何らかの形式のソースをから利用できるようにして いますがFunction#toString、一部のブラウザは(ほとんどの場合モバイルブラウザで)利用できず、仕様で定義されていません。ただし、サポートする特定のブラウザセットがあり、それらすべてにそれがある場合、それが唯一の現実的なオプションになります。ただし、それでも、関数内でどのコードブランチが使用されたかを必ずしも知ることはできません。

于 2012-12-01T10:49:35.377 に答える
2

関数を空白のままにすると、undefinedも返されるため、a、b、cはすべて同じ値を返します。

このようなことを実現する唯一の方法は、実際に関数自体に何らかのフラグを設定することですが、実際の関数の実装とは関係なく、これを実行できるようにしたいと思います。

于 2012-12-01T10:47:16.763 に答える
2

違いを見分ける方法はありません。

本当に必要な場合は、関数のソースコードを分析して、returnステートメントがあるかどうかを判断し、ない場合は、値が返されないと想定します。もちろん、これは、関数が時々戻るかどうかを判断するのが少し難しいでしょう(例えば、if-blockのreturnステートメント)

于 2012-12-01T10:47:41.487 に答える
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番目のパラメーターはパラメーターの配列です。

戻り値は、2つのプロパティを持つオブジェクトでありout、関数の結果を含み、returned関数が返されたかどうかを示すブール値です。

出力例、

returnProxy(someFunction,[1]); // {out: undefined, returned: true}
returnProxy(someFunction,[2]); // {out: "hello", returned: true}
returnProxy(someFunction,[3]); // {out: undefined, returned: false} 
于 2012-12-01T12:07:06.110 に答える
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());
于 2012-12-01T10:58:00.447 に答える