前提・実現したいこと
現在javascriptファイルにtest1,test2,test3という関数があります。
そのjavascriptファイルを読み込んでいるviewをリロードした時、下記(修正前)の関数が呼び出されるように行いたかったので以下(修正前)のような記述をし、リロードしたところ関数はしっかり呼び出せました。
しかし、3つとも似たような関数名だったのでループ処理でリファクタリングしようと思いましたが、関数名の一部だけをiに書き換えてループ処理をしたことが自分は初めてだったので、とりあえず式展開などを行ったり試してみましたが(下記に記述の修正後コード)、関数を呼び出すことができず、解決に至らなかったので対処法をご教示願いたいです。
修正前
javascript
1$(function() { 2 test1(); 3 test2(); 4 test3(); 5});
修正後
$(function() { for (var i=1; i<4; i++) { test`${i}`(); } });
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答6件
0
ベストアンサー
ちょっとサンプルを作ってみました。
処理が、初期化(init)、実行(exec)、後始末(final)の3つに分かれているとして、それぞれの関数をfoo_init、foo_exec、foo_finalと仮定します。hentaimanさんが指摘されているように、evalを使えば、これらをループで呼び出すこと自体はできます。
JavaScript
1function foo_init() { console.log('init') } 2function foo_exec() { console.log('exec') } 3function foo_final() { console.log('final') } 4 5var funcnames = ['init', 'exec', 'final']; 6$(function() { 7 for (var i = 0; i < 3; i++) { 8 eval("foo_" + funcnames[i] + "()"); // 関数呼び出しを文字列として作りevalで呼び出す 9 } 10});
しかし、このプログラムには以下の問題があります。
- ループにしない単純なプログラムと比べて読みにくく、理解しづらい
- evalを使うこと自体は非常によくない(特にセキュリティ上の問題が大きい)
evalを使うことの問題については、以下のQ&Aが参考になると思います。
evalを使わないだけなら、以下のように「関数の配列」を使っても書けますが…
JavaScript
1funcs = [ 2 function() { console.log('init') }, 3 function() { console.log('exec') }, 4 function() { console.log('final') }, 5]; 6 7$(function() { 8 for (var i = 0; i < 3; i++) { 9 funcs[i](); 10 } 11});
はたしてこのプログラムは前よりも改良されているでしょうか?単に以下でよいと思います。
JavaScript
1function foo_init() { console.log('init') } 2function foo_exec() { console.log('exec') } 3function foo_final() { console.log('final') } 4 5// 中略 6 7foo_init(); 8foo_exec(); 9foo_final();
こうすれば、初期化・実行・後始末を順に呼んでいるのだなということがひと目で分かります。
ということで、そもそも「リファクタリング」の方向性が妥当でないのではないかという疑問を持ちました。
投稿2019/11/01 00:54
編集2019/11/04 07:39総合スコア11705
0
飽くまでそういうループの仕方で実行したいならeval
リンク先をよく読んでから使うかどうか判断しましょう
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/eval
でも似たようなfunction名だからという理由だけならちゃんと定義通りの名前で呼んだ方が良いです
似たような機能だからまとめたいという目的があるなら各functionをひとつの配列にまとめてしまえば質問に書いてあるコードに近い書き方でできます
投稿2019/10/31 21:13
総合スコア6426
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
トップレベルで定義された関数、かつより狭いスコープに同名の関数がないという条件であれば、以下のような関数を作れば動かせると思います。
可能というだけでよい書き方かは別ですが…
javascript
1var defineTemplateAccessorFunc = name => { 2 window[name] = (strs, ...vals) => window[name + String.raw({raw: strs}, vals)]; 3}; 4defineTemplateAccessorFunc('test'); 5 6 7$(function() { 8 for (var i=1; i<4; i++) { 9 test`${i}`(); 10 } 11});
投稿2019/11/01 02:06
総合スコア805
0
ockeghem さんの発展
javascript
1// 実際の関数を格納したオブジェクト 2var view = { 3 init : function () { console.log('init') } 4, exec : function () { console.log('exec') } 5, final: function () { console.log('final') } 6} 7 8// 関数名を配列に格納 9var types = ["init", "exec", "final"]; 10, fname 11, i 12; 13for( i=0; i<3; ++i ) { 14 fname = types[i]; 15 view[fname](); 16}
投稿2019/11/01 04:21
総合スコア5434
0
なんの解決にも繋がりませんがsetTimeoutのようなレガシーな関数の
「コールバックを文字列で指定できる」という今となっては
半分バグのような仕様を利用すれば、動かすことはできます
ただし非同期処理の調整などより煩雑になるのでよい選択肢ではありません
(一応できるというだけの話)
javascript
1const test1=()=>{console.log("responce1");}; 2const test2=()=>{console.log("responce2");}; 3const test3=()=>{console.log("responce3");}; 4for(var i=1;i<=3;i++){ 5 setTimeout(`test${i}()`,0); 6}
あ、たしかにグローバルな関数ならwindowの引数で指定できますね
javacript
1function test1(){console.log("responce1");}; 2function test2(){console.log("responce2");}; 3function test3(){console.log("responce3");}; 4for(var i=1;i<=3;i++){ 5 window["test"+i](); 6}
投稿2019/11/01 01:29
編集2019/11/01 02:18総合スコア116688
0
スマホからなので簡単に。
関数を配列に入れてから呼び出すと、関数名に規則性無くても順次呼び出さますよ。
https://qiita.com/_shimizu/items/ae97c4f3208a7c10134a
投稿2019/10/31 22:27
編集2019/10/31 22:29総合スコア2826
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/11/01 15:35