たとえば、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
}
でも、ちょっと不便ですね。もっと簡単な方法はないでしょうか?
ベストアンサー1
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: ...});
ここでa
、b
およびは位置引数であり、最後の引数は名前付き引数を持つオブジェクトです。
例えば:
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
このアプローチにはいくつかの欠点があります(警告しました!)。
- 最後の引数がオブジェクトの場合、「名前付き引数オブジェクト」として扱われます。
- 関数で定義した数の引数が常に取得されますが、そのうちのいくつかには値がある可能性があります(値がまったくないこととは異なります)。つまり、渡された引数の数をテストするために
undefined
を使用することはできません。arguments.length
ラッパーを作成する関数の代わりに、関数とさまざまな値を引数として受け取る関数を使用することもできます。
call(func, a, b, {posArg: ... });
または、Function.prototype
次のように拡張することもできます。
foo.execute(a, b, {posArg: ...});