1. ホーム
  2. ジャバスクリプト

[解決済み】JavaScriptの関数呼び出しで名前付きパラメータを提供する方法はありますか?

2022-03-26 22:19:56

質問

C#の名前付きパラメータ機能は、場合によっては非常に便利だと思います。

calculateBMI(70, height: 175);

これをJavaScriptでやりたい場合、何を使えばいいのでしょうか?


いらないのは、これ。

myFunction({ param1: 70, param2: 175 });

function myFunction(params){
  // Check if params is an object
  // Check if the parameters I need are non-null
  // Blah blah
}

その方法はすでに使っています。他に方法はありますか?

どんなライブラリを使っても大丈夫なんだ。

どのように解決するのですか?

ES2015 およびそれ以降

ES2015の場合。 パラメーターの再構築 は名前付きパラメータをシミュレートするために使用することができます。呼び出し側にオブジェクトを渡す必要がありますが、デフォルトのパラメータも使用すれば、関数内部のチェックをすべて回避することができます。

myFunction({ param1 : 70, param2 : 175});

function myFunction({param1, param2}={}){
  // ...function body...
}

// Or with defaults, 
function myFunc({
  name = 'Default user',
  age = 'N/A'
}={}) {
  // ...function body...
}


ES5

希望に近い方法がありますが、それは、出力が Function.prototype.toString [ES5】の場合] これはある程度実装に依存するため、クロスブラウザに対応しない可能性があります。

関数の文字列表現からパラメータ名を解析し、オブジェクトのプロパティと対応するパラメータを関連付けることができるようにすることです。

関数呼び出しは次のようになります。

func(a, b, {someArg: ..., someOtherArg: ...});

ここで ab は位置引数で、最後の引数は名前付き引数を持つオブジェクトである。

例えば

var parameterfy = (function() {
    var pattern = /function[^(]*\(([^)]*)\)/;

    return function(func) {
        // fails horribly for parameterless functions ;)
        var args = func.toString().match(pattern)[1].split(/,\s*/);

        return function() {
            var named_params = arguments[arguments.length - 1];
            if (typeof named_params === 'object') {
                var params = [].slice.call(arguments, 0, -1);
                if (params.length < args.length) {
                    for (var i = params.length, l = args.length; i < l; i++) {
                        params.push(named_params[args[i]]);
                    }
                    return func.apply(this, params);
                }
            }
            return func.apply(null, arguments);
        };
    };
}());

として使うのはどちらでしょう。

var foo = parameterfy(function(a, b, c) {
    console.log('a is ' + a, ' | b is ' + b, ' | c is ' + c);     
});

foo(1, 2, 3); // a is 1  | b is 2  | c is 3
foo(1, {b:2, c:3}); // a is 1  | b is 2  | c is 3
foo(1, {c:3}); // a is 1  | b is undefined  | c is 3
foo({a: 1, c:3}); // a is 1  | b is undefined  | c is 3 

DEMO

いくつかの 欠点 この方法には、警告が出されています!)。

  • 最後の引数がオブジェクトの場合、"名前付き引数オブジェクト"として扱われます。
  • 関数で定義した数だけの引数が常に得られますが、そのうちのいくつかは、値が undefined (値が全くないのとは違う)。つまり arguments.length を使用して、いくつの引数が渡されたかをテストします。

ラッパーを作成する関数の代わりに、関数と様々な値を引数として受け取る、次のような関数も用意できます。

call(func, a, b, {posArg: ... });

を拡張することもできます。 Function.prototype ということができるように。

foo.execute(a, b, {posArg: ...});