🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
for

for文は、様々なプログラミング言語で使われている制御構造です。for文に定義している条件から外れるまで、for文内の命令文を繰り返し実行します。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

6回答

2138閲覧

javascript関数名をfor文でループ処理させたい

Homaresan

総合スコア15

for

for文は、様々なプログラミング言語で使われている制御構造です。for文に定義している条件から外れるまで、for文内の命令文を繰り返し実行します。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

5クリップ

投稿2019/10/31 20:03

編集2019/10/31 20:06

前提・実現したいこと

現在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ページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答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が参考になると思います。

JavaScript - eval|teratail

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
ockeghem

総合スコア11705

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Homaresan

2019/11/01 15:35

ご回答ありがとうございます!eval初めて知りました!eval()には色々問題があるみたいなので、回答を参考にしながらどのように記述するか自分でもう少し考えて見ます!
guest

0

飽くまでそういうループの仕方で実行したいならeval
リンク先をよく読んでから使うかどうか判断しましょう
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/eval

でも似たようなfunction名だからという理由だけならちゃんと定義通りの名前で呼んだ方が良いです
似たような機能だからまとめたいという目的があるなら各functionをひとつの配列にまとめてしまえば質問に書いてあるコードに近い書き方でできます

投稿2019/10/31 21:13

hentaiman

総合スコア6426

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Homaresan

2019/11/01 15:35

ご回答ありがとうございます!eval初めて知りました!eval()には色々問題があるみたいなので、回答を参考にしながらどのように記述するか自分でもう少し考えて見ます!
guest

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

shinji709

総合スコア805

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Homaresan

2019/11/01 15:43

ご回答ありがとうございます!今回の場合はトップレベルで定義された関数、かつより狭いスコープに同名の関数がないという条件に当てはまるので参考にさせていただきます!
guest

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

AkitoshiManabe

総合スコア5434

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Homaresan

2019/11/01 15:41

ご回答ありがとうございます!なるほど!そのような書き方もあるんですね!参考にさせていただきます!
guest

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
yambejp

総合スコア116688

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Homaresan

2019/11/01 15:38

ご回答ありがとうございます!グローバルな関数ならwindowの引数で指定する方法を試してみます!
guest

0

スマホからなので簡単に。
関数を配列に入れてから呼び出すと、関数名に規則性無くても順次呼び出さますよ。
https://qiita.com/_shimizu/items/ae97c4f3208a7c10134a

投稿2019/10/31 22:27

編集2019/10/31 22:29
oikashinoa

総合スコア2826

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Homaresan

2019/11/01 15:36

なるほどです!ご回答ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問