再利用をする関数の引数が複数ある場合、呼び出し物によって必要な引数と不要な引数がある事が多いですが、引数は順番で、判定するようなので第二引数だけいらない第三だけいらないなど多様なときにどう対処すればよいのでしょうか?
不要な引数の要素も無駄に変数宣言してに取得してあげないとundefinedになって困ります。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答3件
0
ベストアンサー
※ES6を使える環境前提で書いてみます。
function godFunction({ count = 0, isGod = true, list = [], name = ""} = {} ) { //引数を使ったいろいろな処理が間にあると仮定 //とりあえず意味はないがcountをそのまま返す return count; } godFunction({ name: 'teratail', count: 1, isGod: true }) godFunction();
https://repl.it/repls/IdealisticTurboScale
引数をオブジェクトで渡してあげれば、引数をどの順番に渡さないといけないかを気にせずに済むようになります。また初期値を設定してあげれば、undefinedも回避出来ます。
とは言え、場合によって使わない引数がよくあるという状況自体が、1つの関数でいろんなことをやろうとし過ぎているのかもしれませんね。関数合成をして、、、(略)
投稿2018/03/01 10:11
編集2018/03/01 10:40総合スコア2415
0
とりあえず参照しない引数なんてダミーでなにか入れておけばよいでしょう
nullでも渡してあげればいいのでは?
javascript
1function test(){ 2 var arg=arguments; 3 console.log(arg[0]||null); 4 console.log(arg[2]||null); 5} 6test(100,null,200); 7//出力:100,200 8test(100); 9//出力:100,null 10
投稿2018/03/01 09:21
編集2018/03/01 09:24総合スコア114837
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
今すぐ出来る解決手段の1つが引数をオブジェクト1個にする方法です。
一見あり得ない程ダサいですが、ES6でコードを読めばすぐ分かるようになりましたからね。
JavaScript
1var fn = ({name, type, code}) => { 2 console.log(name, type, code); 3} 4console.log(fn({ 5 name: "hoge", 6 type: "request", 7 code: 200, 8})); // "hoge", "request", 200 9// プロパティが足りなくても安心 10console.log(fn({name: "piko"})); // "piko" undefined undefined
別の手段として関数型プログラミングの考えかたから一部輸入してくる方法があります。
カリー化や部分適用と呼ばれる方法です。
「部分適用」の概念が分かりやすいのでこちらを先にやりましょうか。
このfn2やfn3に該当するのが部分適用です。
大げさに「部分適用」みたいなテクニック付けやがって…単純過ぎるだろという怒られが発生しそうですが、
確かに引数1個を要求するけど、2個目や3個目にちゃんと格納されることが確認できます。
JavaScript
1var fn = (val1, val2, val3) => { 2 if (val1 != null && !isValid(val1)) return false; 3 if (val2 != null && !isValid(val2)) return false; 4 if (val3 != null && !isValid(val3)) return false; 5 return true; 6} 7var fn2 = val2 => fn(null, val2, null); 8var fn3 = val3 => fn(null, null, val3);
他にもJavaScriptならではの機能を使って、こんな書き方でも束縛出来ます。
javaScript
1var fn2 = fn.bind(null, null); 2var fn3 = fn.bind(null, null, null);
カリー化はちょっと大変です。
例えば3個の引数を要求する関数の場合、
合計3個の引数が届くまで引数を要求する関数を返し続ける関数のことです。
分かりにくいので、簡単なコードにしてみました。
JavaScript
1// 普通の関数 2var add = (a, b) => a + b 3console.log(add(2, 3)); // 5 4 5// カリー化 6var curried_add = a => b => a + b 7console.log(curried_add(2)(3)); // 5
しかし、このカリー化したadd関数は正当なカリー化ではありません。
上の例では引数1個ずつ渡して発火させましたが、
本来は引数2個でも発火すべきだからです。
JavaScript
1var add = a => b => a + b 2console.log(add(2)(3)); // 5 <- これはまぁその通り 3console.log(add(2, 3)); // (b => a + b) <- 2個目の引数が無視されてる
これ両対応させるの無理じゃね?
そこでちょっと関数を改造します。
JavaScriptの関数は.length
プロパティが存在し、
関数が求めている引数の数を取り出せます。
これを利用して引数が要求数に満ちるまで実行を遅延させる関数を実装することで解決させます。
JavaScript
1var add = (a, b) => a + b; 2console.log(add.length); // 2
JavaScript
1// 書き方キモいけど許して!ごめんね! 2var curry = (fn, ...savings) => 3 savings.length >= fn.length 4 ? fn.apply(null, savings) 5 : (...args) => { 6 const its = [...savings, ...args]; 7 return its.length >= fn.length 8 ? fn.apply(null, its) 9 : curry(fn, ...its); 10 }; 11var add = curry((a, b) => a + b); 12 13// どっちの書き方もいける 14console.log(add(2)(3)); // 5 15console.log(add(3, 4)); // 7 16console.log(add(5, 6, 7)); // 11 <- 多すぎる分は無視 17 18// こんな風に引数1個だけ束縛しておく事も可能 19var add10 = add(10); 20console.log(add10(3)); // 13 21console.log(add10(5)); // 15
毎回このcurryとかいうよく分からんのをコピペして宣言しないといけないのか…
そうではありません。
関数型プログラミングが出来るライブラリのLodashやRamda.jsで定義されています。
これらのライブラリを使えば関数の束縛が非常に楽になります。
Ramda.jsが個人的にはオススメなんですが、Lodashは既に人気があり、多くのプロジェクトが採用しているので、すんなり導入出来るんじゃないでしょうか?
少し長くなりましたが以上です
投稿2018/03/01 11:09
編集2018/03/01 11:12総合スコア21158
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
関連した質問
関数の引数が複数ある場合、呼び出し物によって必要な引数と不要な引数がある事が多いですが、引数は順番で、判定するようなので第二引数だけいらない第三だけいらないなど多様なときにどう対処すればよいのでしょう
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2018/03/01 11:06