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

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

ただいまの
回答率

87.60%

自己定義関数の中に変数を埋め込む方法

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 501

score 256

下記のように自己定義関数sampleの中において、alertの中に変数として
hoge+messageを代入してsample("push")によって、結果として"hello"を返したいのですが
"push_message"として文字列が返されます。

この関数の中のhoge+'_message'を変数として使用したいのですが
どのようにすれば良いのでしょうか?

<button class="push">push</button>
const push_message ="hello";
sample("push")

function sample(hoge){
$('.'+hoge).on('click',function(){
   alert(hoge+'_message');
 })
}

追記

なぜそのようにしたいのかという目的についてご指摘があったため、下記の通り、実際の状況を踏まえて、目的とともに内容を追記させていただきました。

実際にはconst push_messageは配列でこれに対する処理を自己定義関数内で書いております。

<button class="ary1">click</button>

ここで自己定義関数でそれぞれの配列に対して処理を定義する場合に以下のようにするよりも

var ary1_a=[];
var ary2_a=[];
var ary3_a=[];

function sample (cls, cls_a){
$(".”+cls).on('click',function(){
cls_a.push(/*something*/)
})
}

例えば以下のように引数を減らしたほうが後々見通しが良いためというのが目的です

var ary1_a=[];
var ary2_a=[];
var ary3_a=[];

function sample (cls){
$(".”+cls).on('click',function(){
(cls+"_a").push(/*something*/)
})
}

たまたま、以下の条件を満たすため、このような対応をしたいと感がているところです。

  • 2つの引数となるべき一部の文字列(cls)が重複している
  • その後に続く文字列(_a)が適用すべき関数において共通である

なお、eval(hoge+'_message')で対応することは可能かと思うのですが、一般的にevalを使わなくて良い方法があるのであれば仕様は控えるべきと、学んだことがあるため今回使用はしていません

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • kei344

    2019/11/04 22:52

    この「質問への追記・修正の依頼」の部分はデフォルトで表示されませんので、質問本文に追記することをお勧めします。

    キャンセル

  • SugiuraY

    2019/11/04 23:10 編集

    kei344様
    コメントありがとうございます。
    承知をしました、本文に追記をさせていただきます。

    キャンセル

  • think49

    2019/11/04 23:48

    「追記」のコードがコードブロックで括られていないようなので、修正して下さい

    キャンセル

回答 2

checkベストアンサー

+3

event.data

イベントハンドラ関数に値を渡すのであれば、jQueryには event.data が用意されています。

'use strict';
const foo = 'push';
jQuery('.' + foo).on('click', new String(foo), event => console.log(event.data + '_message'));

他に、data-*属性に埋め込む手もあります。

引数を減らす

function sample (cls) {
  $("."+cls).on('click',function(){
    (a[cls]).push(/*something*/)
  })
}

クラス名と変数名(プロパティ名)を一つの変数にまとめて、引数を減らす設計は良いとは思いません。
クラス名と変数名は別の概念であり、同じ名前にする必然性はありません。
同じ名前にしてしまうと、後で変数名を変えた時にクラス名まで変えなくてはなりません。

変数名を一つの名前で固定すると、関数と変数の間に依存関係が出来ます。
変数のスコープは出来るだけ狭くし、参照透過性を持つ設計にするのが、可搬性/汎用性の観点から好ましいと感じます。

data-*属性 + event.data

<input type="button" class="sample" value="push1" data-index="0">
<input type="button" class="sample" value="push2" data-index="1">
<input type="button" class="sample" value="push3" data-index="2">
<script>
'use strict';
function handleClick (event) {
  console.log(event.data[jQuery(event.target).data('index')]);
}

function addClickHandler (selectorText, data, handler) {
  jQuery(selectorText).on('click', data, handler);
}

addClickHandler('.sample', ['sample1','sample2','sample3'], handleClick);
</script>

Re: SugiuraY さん

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/11/05 08:54

    @SugiuraY さん
    私の名前は「@think49」です。

    > "変数名はグローバル変数など、何らかのプロパティになっていなければ、文字列参照は出来ません"

    ページ検索すれば、それは私(@think49)のコメントである事が分かります。
    青を基調としたアイコンを見て、@kei344さんと誤認したのでは?
    アイコンはあてにせず、「名前」を確認して下さい。

    キャンセル

  • 2019/11/05 10:01

    大変失礼いたしました。いま辻褄が合いました。
    完全に私の誤認でございます。ご迷惑をかけたお二方にお詫びいたします。
    以後気を付けます。
    コメント中のお名前についても修正させて頂きます。
    宜しくお願い申し上げます。

    キャンセル

  • 2019/11/06 09:15

    think49様
    コメントありがとうございます。
    ①「クラス名と変数名(プロパティ名)を一つの変数にまとめて、引数を減らす設計」につきまして
    本件、仰る通りでした。私の場合ご記載いただいた内容の反対のケースでクラス名を変更したのですが、当然関数が動作しなくなるので、とてもメンテナンスしづらいことに気づかされました。安易に引数を減らすという考え方がまたバグの温床になるという場合があることについて学ぶことができました。

    ②data-*属性 や event.dataにつきまして
    要素から特定の値を取得する場合にJqueryでこのような方法があることを学ぶことができました。これまでclass="sample"から特定の値を取得する場合、無理やりid="data"を設定し以下のような形で取得させたりしていました。(お恥ずかしいのですが、当然html・DOM構造上望ましくないやり方です)
    $('.class').on('click',function(){ $(this).attr('id')})
    イベントハンドラ関数への値の渡す方法の幅が広がり、活用することができると思います。

    ③、配列を event.data に渡して、引数で受け取る。
    自分で動作を確認することでやっと仰っている意味が分かりました。
    コールバック関数(handler)を中に書かないと自分はまだ簡単に読み解けないので下記は変形していますが、クリックイベントで取得した属性値によって、引数の中の配列( ['sample1','sample2','sample3'])のいずれかを取得するということですね。。なるほど。これまでの自分の知識と想像力では絶対に生み出すことができなかったコードなので、大変勉強になりました。

    addClickHandler('.sample', ['sample1','sample2','sample3']);
    function addClickHandler (selectorText, data, handler) {
    jQuery(selectorText).on('click', data, function (event) {
    console.log(event.data[jQuery(event.target).data('index')]);}
    );}

    また同時に理解できなかったデータの紐づけについては、この配列の要素たちを直接クリックされる要素に備えるのか又はハンドラ関数の中に上記のように持たせるのかという意味で解釈することができました。(推察が間違っていたら申し訳ございません。)

    ④文字列を変数として参照する方法につきまして
    結果的に当初見つけたeval()によって、これを実行することができることがわかりましたが、調べていくと処理速度やセキュリティの面からやはり望ましくないことがわかりました。eval(hoge+'_message')とする方法である。加えて①の設計の面からも今回の件に関しては望ましくはないので、evalでできることはわかったが使用すべきではないという判断で決着しようと思います。

    多くの知見をご提供いただき誠に感謝いたします。
    最後になりますが厚い御礼を申し上げます。

    キャンセル

+1

実際には 。。。。。。

ということであれば、

var ary1_a=[];
var ary2_a=[];
var ary3_a=[];


のような変数を作ってはいけません。

const a = {"ary1":[], "ary2":[], "ary3":[]};

function sample (cls){
  $("."+cls).on('click',function(){
    (a[cls]).push(/*something*/)
  })
}


ですね。

なお、sampleを「自己定義関数」と呼ぶのは違和感があります。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/11/04 23:19

    コメントありがとうございます。

    申し訳ございません、省略すべきでない点を省略しておりました。以下のような状況です。
    var ary1_a=[1,2,3];
    var ary2_a=[4,5,6];
    var ary3_a=[7,8,9];
    従って問題は尾ヒレのようについてくる_aをfunctionの中でどのように表現するかと言う点でございました。

    また一点ご指摘にあった「自己定義関数」についてですが
    Javascriptに標準で備わっているもの「標準関数」「標準メソッド」
    と言う表現に対して自分自身が作り出したものを
    「自己定義関数」や「ユーザー定義関数」
    という名称で慣れてきたのですが、一般的にはこの後者の類はどのように呼んでいらっしゃるのでしょうか?
    よろしくお願いもうしあげます。

    キャンセル

  • 2019/11/04 23:37

    > 省略すべきでない点を省略しておりました。以下のような状況です。
    本質的な違いは無いと思いますが。

    > 一般的にはこの後者の類はどのように呼んでいらっしゃるのでしょうか?
    普通は単に「関数」だと思います。「ユーザー定義関数」は有りです。

    キャンセル

  • 2019/11/04 23:37 編集

    > 自分自身が作り出したものを「自己定義関数」や「ユーザー定義関数」

    イメージの問題かもしれませんが、私は「自己定義関数」を「自己書き換えコード」のように読み取れます。
    関数 sample が自己(関数 sample)を書き換えるコードです。
    https://ja.wikipedia.org/wiki/%E8%87%AA%E5%B7%B1%E6%9B%B8%E3%81%8D%E6%8F%9B%E3%81%88%E3%82%B3%E3%83%BC%E3%83%89
    少なくとも、「自己定義関数」は一般的な用語ではありません。

    ※他人に説明する際には辞書を引いたり、Google検索する等して「一般的な用語」かを確かめる事をお勧めします。

    キャンセル

  • 2019/11/05 00:02

    手元の書籍では該当用語が使用されていたのですが確かにあくまで筆者がそのように読んでいる(読み分けている)だけの可能性もあるので、一般用語か否かは調べてみようと思います。
    一つきっかけになりました、ありがとうございます。

    キャンセル

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

  • ただいまの回答率 87.60%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る