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

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

ただいまの
回答率

87.79%

ローカルスコープの変数を使用できない

解決済

回答 2

投稿 編集

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

score 251

下記のように、コードを記載した場合、
if文の中の
i1、i2_1、i2_2はそれぞれnot definedになってしまいます。
その前のfunction内(ローカルスコープ内)でvar宣言をしてないので、grobal scopeとして使用できるのではないでしょうか?
原因とfunction外で当該変数を使用する方法について、アドバイスをいただければ幸いです。

なお、function内にif文のブロックを書けばと言うご指摘もあるとともいますが、
ここではsetTimeoutをして要素が動的に変化した後の.text()を取得しなければならないことから
このような構造になっております。
setTimeoutを指定しない場合には変化前の要素のtextを取得してしまうため、うまくいきません。。。
このような方法でsetTimeoutを使用すること自体、あまり望ましい使い方ではないと言うご指摘を頂く
きはいたします。。。

よろしくお願い申し上げます。

$(function(){
  $('#select_inside_1>div>div>div,#select_inside_2_1>div>div>div,#select_inside_2_2>div>div>div').on('click', function() {
    setTimeout(function(){
   i1=$('#select_inside_1>div>div:eq(0)').text();
   i2_1=$('#select_inside_2_1>div>div:eq(0)').text();
   i2_2=$('#select_inside_2_2>div>div:eq(0)').text();
  console.log(i1);
},1)
if ((!i1=="【賃貸/購入 選択")&&(!i2_1=="【資産 選択】"||!i2_2=="【資産 選択】")) {
alert('execution');
}

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

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

  • x_x

    2018/02/08 14:09

    本当はtext内容を変える処理があるのですよね? その次に書くということです。

    キャンセル

  • SugiuraY

    2018/02/08 17:35

    $(function(){$('#hoge').on('click',function(){($('#foo').text('abcd'));alert($('#foo').text())...といったイメージでしょうか。

    キャンセル

  • SugiuraY

    2018/02/08 17:37

    すみません、個々でのコードはあまりにも見づらかったですね。。。

    キャンセル

回答 2

checkベストアンサー

+3

まず、インデントが崩れているので読みづらいですが、それはいったん置いておきます。

そして、「暗黙のグローバル変数」は今時のJavaScriptでは使うべきでない機能です。'use strict';と書いた場合やクラスの中、ES Moduleの中では無効になります。内側で事前に宣言しておけば、さらに内側でも使えます。

$(function(){
  var i1, i2_1, i2_2; // ここでローカル変数として宣言
  $('#select_inside_1>div>div>div,#select_inside_2_1>div>div>div,#select_inside_2_2>div>div>div').on('click', function() {
    setTimeout(function(){
      i1=$('#select_inside_1>div>div:eq(0)').text();
      i2_1=$('#select_inside_2_1>div>div:eq(0)').text();
      i2_2=$('#select_inside_2_2>div>div:eq(0)').text();
      console.log(i1);
    },1)
    if ((!i1=="【賃貸/購入 選択")&&(!i2_1=="【資産 選択】"||!i2_2=="【資産 選択】")) {
      alert('execution');
    }
  });
})

さらに、setTimeoutしているので、if文はsetTimeoutの中身より先に実行されます。取ってきてもundefinedになるのは、まだセットしていないからです。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/02/08 13:58

    コメント有難うございます。そのような変数の使い方を「暗黙のグローバル変数」とよび、非推奨の使い方なんですね。今回であれば、後から実行されるif文のブロックにもsetTimeoutで2以上を設定すれば、セットされるということなのでしょうが、あまり望ましくないということですね。
    動的に変更したあとの$('#select_inside_1>div>div:eq(0)').text();を取得したく、タイムラグを私用しており、またこの動的に変更される要素はクリックされる要素自体がトリガーになっているので、時間差でtext()を取得しようというアイデアに至りました。
    しかし、今実行結果を確認したのですが、同じスコープ内に書いてある console.log(i1);で動的に変更後のテキストが取得できているのでif文のブロックもおなじ内側にかけることに気がついたのですが、こうなると何故setTimeout内のconsole.log(i1);が変更後のtextを取得できてしまったいるのか不思議です。。

    インデントについては、一人でしか開発をしたことがないので、強く意識したことがないのですが、
    ネスト化するためにインデントをおき、階層がふかくなるたびに右側によっていくというところが一般的に見易いのでしょうか?

    キャンセル

  • 2018/02/08 14:20

    > 何故setTimeout内のconsole.log(i1);が変更後のtextを取得できてしまったいるのか不思議です。。

    変更後だからです。

    キャンセル

  • 2018/02/08 17:19

    コメント有難うございます。
    setTimeout(function(){
    //処理1;
    //処理2;
    },1)
    は1/1000秒後に処理1と処理2を同時に行うため、変更されないと勘違いをしていました。
    処理1でテキストが変更してその後処理2で変更後のテキストが取得できるのですね。
    1/1000秒後の処理で同時ながらも上から順番に処理されることを理解いたしました。

    キャンセル

  • 2018/02/08 17:24

    なお、この場合の「1」というのは実質的な意味はありません。正確に1ミリ秒ということではなく、「onclickで動く他のイベントが片付いたら」実行される、ということになります。

    キャンセル

+2

setTimeoutを利用している目的がわかりません。
同処理は非同期なので後ろの処理が意図しているより先に(つまり同時に)
走ってしまっているのでは?

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/02/08 14:02

    yambejp様
    いつもコメントありがとうごさいます。
    仰るとおりの点が原因であることがわかりました。ただ、反対にsetTimeoutのブロック内で出力している
    console.log(i1);が動的に変更後のテキストを出力しているのが読み解けなくなりました。。
    今回はクリックされる要素によって、text();の内容が変わるため、変わった後のテキストを取得すべきsetTimeoutで意図的に変更後の要素を取得しようとタイムタグを設けました。しかし、上でも言及しましたが、console.log(i1);がsetTimeoutのブロック内に書かれているのに変更後のテキストが取得できているのが謎なので、すこしsetTimeoutの仕様を調べてみようと思います。

    キャンセル

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

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

関連した質問

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