質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.50%
JavaScript

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

Q&A

解決済

5回答

10727閲覧

関数を変数名で呼び出す

ssmxgo

総合スコア178

JavaScript

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

2グッド

3クリップ

投稿2016/09/06 07:33

編集2016/09/06 11:17

javascript超初心者です。(PHP、VBは基礎の基礎レベルは分かります)
掲題の件ですが、掲題の件をどのようにすれば実現できるかご教授ください。

javascript

1 2function test_1(){ 3return 'test1'; 4} 5 6function test_2(){ 7return 'test2'; 8} 910 11 12for (var i=1 ; i<=3 ; i++){ 13 console.log( 'test_'+i+'()' ); 14}

こちらを参考にfor文の部分をこのように変更しましたがNG

javascript

1window['test_'+i]();

javascript

1console.log( window['test_'+i]() );
Kota.Y, act823👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

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

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

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

guest

回答5

0

ベストアンサー

JavaScript

1function test_1(){ 2 return 'test1'; 3} 4function test_2(){ 5 return 'test2'; 6} 7var array = [ test_1, test_2 ] 8for ( var i=0 ; i<2 ; i++ ) { 9 console.log( array[ i ]() ); 10} 11```とか。 12 13--- 14 15**追記:** 16 17下記をtest.htmlとか名前を付けてUTF-8で保存し、ブラウザで開いてみてください。 18 19```HTML 20<!DOCTYPE html><html><head><meta charset="utf-8"> 21<title>test_1</title> 22</head><body> 23<script> 24function test_1(){ 25 return 'test1'; 26} 27function test_2(){ 28 return 'test2'; 29} 30for (var i = 1 ; i < 3 ; i++){ 31 console.log( window['test_'+i]() ); 32} 33</script> 34</body></html>

投稿2016/09/06 08:11

編集2016/09/06 12:11
kei344

総合スコア69364

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

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

ssmxgo

2016/09/06 08:14

有るがとうございます。 どうもPHPから来たからか、ココらへんが少し理解できません(先ほど似たコードをテストしたので稼働することは間違いなさそうですね!) `array[i]()` と `'test_1'()` の違いが理解できません(汗)
think49

2016/09/06 08:22

test_1 は関数を参照しますが、"test_1" は文字列を参照します。 "test_"+i も文字列なので、関数を参照できないという事ですね。 window と "window" の違いのようなものです。 console.log(window); console.log("window");
ssmxgo

2016/09/06 08:32

`array[1]()` はarray配列の添字1に設定された文字列…という意識でしたが、先ほど別のコメントでもありましたが、すでにこの時点での認識があやなっていて、文字列ではないのですね。 確かに、arrayとは有りますがjsはオブジェクト扱いだったような。(オブジェクトはワタシ的には仙人の領域ですが)
think49

2016/09/06 08:44 編集

> `array[1]()` はarray配列の添字1に設定された文字列…という意識でしたが 配列の添え字は文字列で合っています。 オブジェクトのプロパティ名もSymbol型を除ければ文字列ですね。 ですので、window['test_'+i]() や array[i] が機能しています。 (質問文のコードも test_1 がグローバル変数なら期待通りに動作します) > 確かに、arrayとは有りますがjsはオブジェクト扱いだったような。 はい、配列や関数はJavaScriptではObject型です。
kei344

2016/09/06 08:45 編集

To: think49さん 補足ありがとうございます! To: ssmxgoさん 「array[i]()」は、変数名「array」の配列の「i」番目に入っているモノ(テキストや数字や配列や関数やオブジェクトが入る)を、「たぶん関数」と決め付けて「()」で実行しています。下記コードと同じようなことだと思えばよいと思います。 var fn = array[i]; fn();
ssmxgo

2016/09/06 09:00

think49さん > すみません、kei344さんご本人かと思っていました。 はぁぁぁ〜〜〜〜〜〜。なるほどです。 グローバル変数はうまく出来ませんが理屈的には理解できそうです!! kei344さん、ありがとうございます この挙動の癖には驚きました、ホント驚きました。やはり fn = "test_"+i; console.log( fn() ); では実行できないところから見ると、オブジェクト型がポイントですね
kei344

2016/09/06 09:04

fn = "test_"+i; は中にテキストが入っているだけです。なので実行できません。 fn = function(){ return 'text' }; とかしていたら実行出来ます。 ちなみに fn = function(){ return function(){ return 'text' } }; console.log( fn()() ); // 'text' とかできます。
ssmxgo

2016/09/06 09:14

一番下は神の領域でそっとじになってしまいますm(_ _)m とか思いましたがよく見てたらわかりました。 う〜ん、いずれにしてもわかったんですけど、感覚的にはまだしっくり来ませんがこの辺は慣れですよね。functionとおしてもreturnで文字列返ってきたらfnも文字列じゃね?ってw感覚がなかなか切り替わりません そーゆーものだ、そう癖にしようと思いますが…う〜ん、難しいというか不可解というか。なぜ文字列がreturnされてるのに、関数実行しちゃうんですかね(長いw) 申し訳ないので、ココらへんで皆さんのアンサーをトリガーにして勉強できそうです。 しかし、ベストアンサーに困りましたね。ほんと皆さんにお贈りしたいです
kei344

2016/09/06 09:18

> functionとおしてもreturnで文字列返ってきたらfnも文字列じゃね? 「fn = function(){ return 'text' };」は関数をfnに入れています。ここで実行されていません。なので、文字列は返っていません。 fn = ( function(){ return 'text' } )(); こうするとこの場で実行されるので、fn には文字列が入ります。
ssmxgo

2016/09/06 09:38

そ、そうですか。よくよく考えてみれば「無名関数」なのでこれはPHPも然りで私の認識違いかもしれませんね…が、エラーで検証できず。実は重ねてこれも実験したかったけ土ダメみたい。 function fn(){ return 'text'; } console.log( fn()() );
ssmxgo

2016/09/06 09:39

なんか親切にしてもらいすぎてて恐ろしくなってきました(汗) ありがとうございます
kei344

2016/09/06 10:10

> console.log( fn()() ); console.log( fn() ); // 中のreturnがテキストを返しているので、()()とやると失敗します > なんか親切にしてもらいすぎてて恐ろしくなってきました そういうサイトです(笑)。がんばる人には優しいサイトです。
ssmxgo

2016/09/06 10:56

ホントありがとうございます。できるだけ自力で解決しようと思ってますがいつも助けられてます。 やはりfunctionはテキストを返すのですね、無名関数でなくてはダメですね、と言いたいところですが…なぜかな、うまく行きません。 https://paiza.io/projects/ihJpMfqFY4LryqdGqIo7AA
kei344

2016/09/06 11:53

var fn = "test_"+i; // テキストを入れている console.log( fn() ); // テキストを無理やり関数として実行しようとしている(無理)
kei344

2016/09/06 11:59

関数宣言 した関数を関数名を合成することで呼び出すことは難しいと思います。配列やオブジェクトに関数を代入することで問題は解決するはずです。
think49

2016/09/06 12:21

おそらく、関数オブジェクトを参照で代入しているイメージが出来てないのだと思います。 「JavaScript 参照渡し 値渡し」でGoogle検索すると見えてくるものがあるのではないかと思います。
kei344

2016/09/06 12:42

To: think49さん 参照渡し 値渡しは躓きやすいですよね。 なんとなく、下記 test1 / test2 を混同しているのではないかと思います。 function fn1(){ return 'text'; } var test1 = fn1; // 関数オブジェクト var test2 = 'fn' + 1; // テキスト console.log( test1() ); console.log( test2() ); // error 【PHP: 可変関数 - Manual】(これと混同してそう) http://php.net/manual/ja/functions.variable-functions.php
think49

2016/09/06 13:25

今までのコードをまとめるとこんなところでしょうか。 https://jsbin.com/noyotusuno/edit?js,console 個人的には kei344 さんが提案された array 案を推します。 「eval is evil」ですし、グローバル変数は出来るだけ避けた方が他に干渉しなくて済みます。 他にあがってないコードとしてはオブジェクトのプロパティに埋め込む方法もありますね(原理は配列と同じですが)。 var obj = {test1: function () {}, test2: function () {}};
ssmxgo

2016/09/07 01:04

お返事遅くなりました! 今回はコレがキーになりそうです!!!ありがとうございます おそらく、関数オブジェクトを参照で代入しているイメージが出来てないのだと思います。 「JavaScript 参照渡し 値渡し」でGoogle検索すると見えてくるものがあるのではないかと思います。
ssmxgo

2016/09/07 01:15

think49さん、コードありがとうございます。 jsbinで動いてるのにPaizaでは動かなかった(;´Д`)Paizaだめじゃん evalで実現してましたが、PHP以上に表?に露出するJSではセキュリティ的にコワイので、arrayで実現させるように努めます
ssmxgo

2016/09/07 02:01

今回、本当にお時間を割いていただき、また問題の根本まで探り当てていただき感謝です。ご指摘のポイント学習いたします ありがとうございました! 特にthink49様は直接的な評価を差し上げられず申し訳ありません。
guest

0

javascript

1 console.log( this['test_'+i]() );

だと動作しましたが、環境によるかもしれませんね。

投稿2016/09/06 09:20

Lhankor_Mhy

総合スコア35869

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

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

ssmxgo

2016/09/06 09:36

ありがとうございます。 ごめんなさい、this[]を知らないので少し調べますのでコメントお待ち下さい 申し訳ありません
ssmxgo

2016/09/06 11:23 編集

あーあーあー。意味わかったかも…しれません。 []はわかりませんが、this自体が関数を呼び出すものなのですね。 しかし、 console.log( 'test_'+i+'()' ); と置き換えてもやっぱり動きません これが出来れば理想ですね
guest

0

結構無理やりになりますが・・・
'test_'+i() ←の形だと【test_】 は文字列として扱われるので、変数の扱いにはなりません。

なので、各functionを配列にいれて実行

script

1var array=[ 2 test_1(),test_2() 3] 4for (var i=0 ; i<=1 ; i++){ 5 console.log( array[i] ); 6} 7 8

ですかね???
でも、あまり正当な気もしないので、あくまで無理やり案だと思ってください。

投稿2016/09/06 07:47

chiro.0519

総合スコア118

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

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

ssmxgo

2016/09/06 08:02

えええええ!!??。 ちょっと衝撃です。 これで動くのかな?と思いましたが動きましたねぇ(汗) イメージ的にはarray[1]も’test_’+i()も等しく文字列のイメージだったので、片方が動いて片や動かない…というjavascriptのお作法が理解できません(;´Д`)衝撃 もしかしたらこれで解決できそうな気もしてきましたが…、(汗)jsがわからなくなりそうです(笑) 自分内での常識をくつがえす内容でした。本当に勉強不足です
ssmxgo

2016/09/06 08:06 編集

ああ、'test_'+i='()' にすればいいのかな? と、こちらを実行しましたがダメでしたね。文字列が表示されただけでした ``` for (var i=1 ; i<=2 ; i++){ console.log('test_'+i+'()'); } ``` test_1() test_2() これを、kodaiさんのようにevalにすれば良いのでしょうけど、狐につままれたような感覚
chiro.0519

2016/09/06 08:06

私もまだまだ勉強中ですが、思うに。。。 ダブルクォーテションで囲わないので、文字列にはならないと思います。多分
chiro.0519

2016/09/06 08:10

eval() は、phpのsessionと同じで、使いやす分怖い所もあるのかと思って。。。 結構、eval()は安易に使わないといった記事も目にするので、怖いかと・・・
kodai

2016/09/06 08:11

結果だけは同じですけど期待しているものとは違うと思いますよ。 最初の `array` の定義時に関数が実行されて、戻り値が配列に格納されているだけです。次の for ループではその結果を出力しています。 関数の実行タイミングは for の中ではなく array の定義時です。
ssmxgo

2016/09/06 08:17

ええええ、kodaiさんのお答えも衝撃です。え〜、定義の時に裏で実行されてしまうのですか?そうしたら、jsは定義にも最新の注意を払わないとイケないんですね(汗) すごい勉強になりました
ssmxgo

2016/09/06 08:19

chiro.0519様、ありがとうございます。ダブルとシングル、調べてみます☆感謝 eval問題はPHPも同様に有りましたので、改めてコードに問題がないか確認してみます。
toutou

2016/09/06 08:26

すいません、とても気になったので書かせてもらいます。おそらくですが’test_’+i()だとtestという文字とi()という関数を足してみたいな意味になるのかと。'test_'+i='()'もtestと言う文字と()と言う文字を+i=してください見たいな感じになるのかな。そしてこんな式はおそらくない。あってるかは不安です。 シングルクォーテーションについてはこれかな。http://qiita.com/niusounds/items/f21a28e862a68a098ea7
ssmxgo

2016/09/06 08:39

ごめんさない +i= は書き間違いです(;´Д`)シツレイシマシタ console.log('test_'+i+'()'); しかし、こちらでも失敗です。" ’ を切り替えましたけど同じ結果だった理由も納得しました。 ありがとうございました
ssmxgo

2016/09/06 08:40

今回はarrayはjsではオブジェクト(←無知)で、array[x]は文字列ではなく、function実行がなされる(実行結果がすでに代入)。 つまり、関数の実行はオブジェクトにより実行された。文字列をつなげて関数呼び出し名を作ったとしても、evalでしか実行できない…こんな結論に至りました
toutou

2016/09/06 08:57

for (var i=1 ; i<=3 ; i++){ console.log('test_'+i+'()'); } これであれば test_1() test_2() test_3()がでますね  var aaa="bbb" console.log(aaa); //bbb console.log("aaa"); //aaa ””の間に入るのは変数ではなくそのままの意味 変数ならつけない
ssmxgo

2016/09/06 09:06

toutouさん、ありがとうございます。 最後に書かれた内容は存じています。多分引っかかっているのが var array = ['test_'+i+'()']; array[1]='test_1()'; A console.log(array[1]); B console.log('test_1()'); A=B と解釈してしまい、JSのお作法がわかりませんでした。 ※補足:ただAの時点で関数の結果の文字列が入っているので厳密には違うっぽんですが
toutou

2016/09/06 09:30

一緒だと思うんだけどな。 var array = ['test_'+'()']; array[1]='test_1()'; console.log(array[1]); //test_1() console.log('test_1()'); //test_1() これだったら一緒。 元々のやつだとiはどっから来たんだってことになるからおかしいな。
ssmxgo

2016/09/06 09:42

最初のは少し間違えましたね 'test_'+i+'()' ですね。ちょっと書いていただいたコード吟味させて頂きます!
toutou

2016/09/06 09:42

なんだかんだで配列に入れて処理するのが一番わかりやすく手っ取り早いという結論に自分は至りました。ちゃちゃいれすみませんでした。
toutou

2016/09/06 09:44

ちなみに試したコードは for(var i=1;i<=2;i++){ console.log('test_'+i+'()'); //test_1() } こっちもあったけどこれだと変数が意味なくなるので自分の中では不採用になりました。
ssmxgo

2016/09/06 10:46

いえいえ、全っ然! むしろ、再確認する機会を頂いています!ありがとうございます
ssmxgo

2016/09/06 10:47

console.log('test_'+i+'()'); こちらで関数呼び出せますか???
toutou

2016/09/06 11:27

説明が下手なんですが仮に' 'で囲んだ文字列を日本語としましょう。囲んでない変数や関数を英語と考えるとしましょう。あなたは英語から日本語にすることは出来ても、英語から日本語にはできません。それを踏まえたうえで 'test_'+i+'()' をみると'test'と’()’はそのままですよね。iはどうなるとかというとそろえるために日本語に直します。var i="aa"としましょうか。つまりこれは日本語のtest_aa()になるわけです。しかしこれは英語ではなく日本語、つまり関数ではないわけです。で、これを英語に直すためには’’をあらかじめ取っておくか、翻訳家のevalさんに来てもらいます。この方に全部翻訳して関数にしてもらいます。ここらへんの説明はほかの方がやってくれてるのでそちらのほうの参照を。よってそのままでは関数ではないので関数の呼び出しはできません。と言う説明でいいのかな、自信ないわ。
ssmxgo

2016/09/06 11:45

わかりやすいです! お願い→もう一歩踏み込んで、今回盛り上がってるのはevalの利用ではなく、 fn = function(){var i=1; return 'test_'+i+'()'; }; console.log( fn() ); のような形式で動くと言われるパターンと var array=['test_1()'] console.log( array(1) ); みたいなパターンです。幾多の答えと若干かぶるかもしれませんが、' 'で囲われた日本語は、オブジェクトや無名関数を通すことで、英語になるというのがjavascriptのお作法ということでしょうか?
ssmxgo

2016/09/06 11:46

もし、多少のコードミスがあったらお許し下さい
toutou

2016/09/06 12:09

fn = function(){ var i=1; return 'test_'+i+'()'; } console.log( fn() ); の結果を見てわかるんですがfn()が返してるのは日本語のtest_1()です。この時点で無名関数を通してもかわらないということがわかります。つまりこれを関数にするためには何かをしないといけないのです。やはり翻訳家が必要です。このルールはjavascriptだけではないと思います。PHPでも似たようなのがあったはずです。
ssmxgo

2016/09/07 01:19

ありがとうございます。 ご指摘の通り、PHPでもそうです。 が、今回みなさんのご指摘をうけ、JSに仕様がそんな感じだと受けとめたのでこのように書きました→つまり混乱してます(笑) それで、その混乱の大元を指摘いただけたのでそれに対して学習してみるとします。 引用: think49 think49 2016/09/06 21:21 おそらく、関数オブジェクトを参照で代入しているイメージが出来てないのだと思います。 「JavaScript 参照渡し 値渡し」でGoogle検索すると見えてくるものがあるのではないかと思います。 通報する kei344 kei344 2016/09/06 21:42 To: think49さん 参照渡し 値渡しは躓きやすいですよね。 なんとなく、下記 test1 / test2 を混同しているのではないかと思います。 function fn1(){ return 'text'; } var test1 = fn1; // 関数オブジェクト var test2 = 'fn' + 1; // テキスト console.log( test1() ); console.log( test2() ); // error 【PHP: 可変関数 - Manual】(これと混同してそう) http://php.net/manual/ja/functions.variable-functions.php
toutou

2016/09/07 01:42

勘違いはあるあるなので気にせずに。あらためて自分も認識を深めることが出来そうです。ありがとうございます。
ssmxgo

2016/09/07 01:59

最後までお付き合いいただいたのでベストアンサー差し上げられず申し訳ありません。 また何か有りましたら、ご教授くださいませ。 今回は、toutou様はじめ、皆様本当にありがとうございました。
guest

0

はじめまして!

Javascript

1<script> 2 var test_1 = function(){ 3 return 'test1'; 4 }; 5 var test_2 = function(){ 6 return 'test2'; 7 }; 8 var test_3 = function(){ 9 return 'test3'; 10 }; 11 var test; 12 for (var i=1 ; i<=3 ; i++){ 13 eval(("test = test_"+i+"();")) 14 alert(test) 15 } 16</script>

取り急ぎ、こんな感じでしょうか?
肝は eval() かな、と思います。
ループ内で動的な変数を指定する際などに便利ですよ^^

投稿2016/09/06 07:54

MaShiRo_H

総合スコア328

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

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

ssmxgo

2016/09/06 08:11

ありがとうございます!実現しました。 更にずれた質問して重複して失礼なんですが、無名関数を敢えて使われたのは意味深ですか?
guest

0

eval()で文字列をコードとして実行できます。

javascript

1function test_1() { 2 console.log('test_1!'); 3} 4eval('test_' + 1 + '();');

投稿2016/09/06 07:49

kodai

総合スコア759

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

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

ssmxgo

2016/09/06 07:55

なるほど、evalは少し頭にうかんがのですがやはりそれですか! ありがとうございます。 更に質問するのも失礼なのですが、function側に表示を持ってきたのは(私は呼び出し側に表示を設置)、意味深ですか?
kodai

2016/09/06 08:00

> 更に質問するのも失礼なのですが、function側に表示を持ってきたのは(私は呼び出し側に表示を設置)、意味深ですか? とくに意味はありません。呼び出されているのを確認したかっただけです。
ssmxgo

2016/09/06 08:09

ありがとうございます、成功しました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問