0
function fnDrawPrism(length, width, height){
        //If any of these parameters are undefined, throw an error that lists the missing parameters.
        return length*width*height;
}

JavaScript では、関数内のすべてのパラメーターの名前を取得しようとしていますundefined。この関数のパラメーターのいずれかが未定義の場合、不足しているパラメーターの名前をリストするエラーを関数にスローさせたいと考えています。

この問題の解決策を見つけましたが、パラメーターごとに個別の条件文が必要であり、未定義のパラメーターのリストを取得するより簡潔な方法があるかどうかを知りたいです。

var toReturn = "";
if((typeof length == "undefined") || (length == "undefined")){
    toReturn += "length is not defined!";
}
if((typeof width == "undefined") || (width == "undefined")){
    toReturn += "width is not defined!";
}
if((typeof height == "undefined") || (height == "undefined")){
    toReturn += "height is not defined!";
}
if(toReturn != ""){
    throw new Error(toReturn); //if any parameters are missing, then list the names of all missing parameters
}
4

6 に答える 6

2

以下は、任意の関数から使用できるスタンドアロンの検証関数で、渡された引数の存在と、ハンガリー語表記を使用した型の正確性をチェックします。

function fnDrawPrism(length, numWidth, intHeight){
    //If any of these parameters are undefined, throw an error that lists the missing parameters.
    // you can cut-and-past the declaration line to fill out 90% of the validation call:
    validate(fnDrawPrism, length, numWidth, intHeight); 

    return length * numWidth * intHeight;
}

// this is cut-and-pasted into a file somewhere, edit to add more types or stricter checking
function validate(args){
    var fn = args, actuals = [].slice.call(arguments, 1),
        hung = {int: "Number", num: "Number", str: "String", arr: "Array",
        obj: "Object", inp: "HTMLInputElement", dt: "Date", bln: "Boolean",
        rx: "RegExp", frm: "HTMLFormElement", doc: "HTMLDocument"},
        names = String(fn).split(/\s*\)\s*/)[0].split(/\s*\(\s*/)[1].split(/\s*\,\s*/),
        mx = names.length, i = 0;
    if(!fn.name)
        fn.name = String(fn).split(/\s*(/)[0].split(/\s+/)[1] || 'anon';
    for(i; i < mx; i++){
        if(actuals[i] === undefined)
            throw new TypeError("missing arg #" + i + " in " + fn.name + " - " + names[i]);
        var hint = hung[names[i].split(/[A-Z]/)[0]],
            got = toString.call(actuals[i]).split(/\W/)[2];
        if(hint && got !== hint)
            throw new TypeError("Wrong type in argument #" + i + " of " + fn.name + " - " + names[i] + ". Got: " + got + ", Expected: " + hint);
}

//try it out:
fnDrawPrism(1);       //! missing arg #1 in fnDrawPrism - numWidth
fnDrawPrism(1,4);     //! missing arg #2 in fnDrawPrism - intHeight
fnDrawPrism(1,2,3);   // ok
fnDrawPrism(1,"2",3); //! Wrong type in argument #1 of fnDrawPrism - numWidth. Got: string, Expected: number

「引数」をバリデーターに渡すことができない理由は、厳密モードでは引数オブジェクトに多くの制限が課せられ、確実に使用できないためです。Ecma6にはすべての引数を一度に渡す方法がありますが、それは将来のブラウザーでのみ機能しますが、長い方法はブラウザーで当時、現在、そして永遠に機能します...

編集: コメントに基づいて検証ルーチンを更新し、ドキュメント、入力、フォーム、配列、正規表現、日付、およびオブジェクトをハンガリー語表記の検証ルーチンに追加して、少し強力にします。これは、ウィンドウ オブジェクト全体でも機能するようになりました。

于 2013-06-30T05:09:12.027 に答える
1

あなたは正しい道を進んでいます-これをヘルパー関数に抽出し、不足しているすべての引数をリストすることでスローされるエラーをより有益にする方法は次のとおりです。

function validateParams(names, vals) {
    var missing = [];
    for (var i=0; i<names.length; i++) {
        if (vals[i] === undefined) missing.push(names[i]);
    }
    if (missing.length > 0) throw "Missing arguments: " + missing.join(', ');
}

function fnDrawPrism(length, width, height){
    validateParams(['length', 'width', 'height'], [length, width, height]);
    return length * width * height;
}
于 2013-06-30T05:20:46.700 に答える
0

私の意見では、より一般的な「Argument 2 is missing」タイプの例外で十分です。開発者は、そのような例外を見てから、引数 2 が実際に何であるかを確認します。また、「欠落」よりも「未定義」について話すほうがよいかもしれません。なぜならfnDrawPrism(undefined, 1, 2);、最初の引数が実際には「欠落」していないという人がいるかもしれないからです。

とにかく、名前を表示することに決めた場合は、ここに私が思いついたものが.toString()あります。関数で正規表現を使用して引数名を取得します。

function fnDrawPrism(length, width, height){
    var msg = [],
        argNames = fnDrawPrism.toString().match(/\(([^)]*)\)/)[1].split(/\s*,\s*/);
    for (var i = 0; i < fnDrawPrism.length; i++)  // for each declared argument
      if (typeof arguments[i] === "undefined")
          msg.push(argNames[i]);
    if (msg.length > 0)
        throw new Error("fnDrawPrism missing argument(s): " + msg.join(", "));

    // ACTUAL function body goes here
}

すべての関数で同様の検証を行いたいと仮定すると、それを別の関数に引き出すことができます。

function testFuncArgs(fn, args) {
    var msg = [], argNames = fn.toString().match(/\(([^)]*)\)/)[1].split(/\s*,\s*/);
    for (var i = 0; i < fn.length; i++)   // for each declared argument
      if (typeof args[i] === "undefined")
          msg.push(argNames[i]);
    if (msg.length > 0)
        throw new Error("Function "+fn.name+" missing argument(s): "+ msg.join(", "));
}

function fnDrawPrism(length, width, height){
    testFuncArgs(fnDrawPrism, arguments);

    // ACTUAL function body goes here
}

function someOtherFunction(a, b, c, d){
    testFuncArgs(someOtherFunction, arguments);

    // Actual function body here
}

誰かがあまりにも多くの引数を指定して関数を呼び出した場合、つまりif (arguments.length > fnDrawPrism.length).

于 2013-06-30T05:19:59.637 に答える