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

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

ただいまの
回答率

88.58%

JavaScript 変数の存在チェック is not defined の解決方法

解決済

回答 4

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 4,633

pinoko

score 79

取得した値を元に、動的に変わる変数をtypeofで存在チェックをしているのですが、is not defined とエラー出力されてしまいます。
なにが間違っているのでしょうか?宜しくお願いします。

エラー内容
// ReferenceError: text5 is not defined

var text1 = 'hoge1',
    text2 = 'hoge2',
    text3 = 'hoge3';

var getNum = 5;
var setText = 'text' + getNum;

if(typeof eval(setText) !== 'undefined'){
    console.log(eval(setText));
} else {
    console.log('なし');
}
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

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

  • m.ts10806

    2018/11/05 16:26

    質問は編集できるので、この「質問への追記、修正の依頼」があったときには質問本文に追記して返してください。

    キャンセル

  • m.ts10806

    2018/11/05 16:37

    ちなみにこれeval()いれる意味ないですよね。typeof setText だけで同じ結果(今回の場合、getNumに1~3を入れるとhoge1~3が表示される)

    キャンセル

  • pinoko

    2018/11/05 17:21

    getNumで取得される値が必ずしも1~3ではないので、例えば5の値を取得した時、存在しない変数なら処理をしたいと思ったわけです。 eval()を入れないと式が評価されず、変数の確認が出来ないです。

    キャンセル

回答 4

+5

取得した値を元に、動的に変わる変数をtypeofで存在チェックをしているのですが

こんな回りくどいことをせずに、配列あるいはオブジェクトとしてtexts変数を用意して、texts[getNum]のように使うようにしましょう。evalは、可能な限り使うことを避けてください。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/11/05 18:01

    ご回答ありがとうございます。
    元のソースが変数宣言されていて、そこに固執してしまって配列にするという考えが出てきませんでした。
    配列で書き直しましたのでその問題は解決しました。
    ただし質問したエラーの原因がわからないのでクローズせずもう少し質問を仰ぎたいと思います。

    キャンセル

checkベストアンサー

+2

知りたいのは「理由」でしょうか。

なにが間違っているのでしょうか?宜しくお願いします。

typeof 未定義識別子 は確かにエラーを出しません。

しかし
typeof eval(未定義識別子) もエラーを出さないだろう、
というのは単なる思い込みで、

実際は、typeofより先に評価されるeval関数の中でエラーが発生してしまい
typeof にまで行かないで終わってしまう、ということでしょう。

===

例えば5の値を取得した時、存在しない変数なら処理をしたいと思ったわけです。 
eval()を入れないと式が評価されず、変数の確認が出来ないです。

evalを使わないで済む方法を推奨しますし、具体例はほかの回答者さんのとおりです。

しかし、万が一、どうしても、文字列から変数の有無を確認をしたいのであれば、
先にtypeofより先にeval単体で検査すればよい、ということが、上記の理屈から分かることと思います。

var text1 = 'hoge1',
    text2 = 'hoge2',
    text3 = 'hoge3';

var getNum = 5;
var setText = 'text' + getNum;

try{
  eval(setText);
}catch(error) {
  console.log("なし");
  setText='';
}

console.log(eval(setText));

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/11/05 18:53

    ご回答ありがとうございます。
    まさにこの回答です。

    evalでエラーを出していた、なので変数存在チェックをと思いましたが、そのエラーの意味を履き違えていたということですね。
    eval自体がエラーで、その際の確認にtry catchが必要だったということですか。

    勉強になりました。ありがとうございます。

    キャンセル

+1

どうしてもというならこうですかね?

var text1 = 'hoge1',
    text2 = 'hoge2',
    text3 = 'hoge3';
var getNum = 5;
var setText=(typeof this["text"+getNum]!=="undefined")?this["text"+getNum]:"none";
console.log(setText);

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/11/05 18:14

    たしかに var を書かなければ大丈夫ですが、
    ただし、“use strict”を使うと、変数の宣言をしていないわけなのでエラーになってしまいます。

    そもそもなぜ var で宣言すると none になってしまうのかがわからないです…

    キャンセル

  • 2018/11/05 18:24

    > use strict”を使う

    そういうことなら、window.addEventListenerの外側で宣言してください

    'use strict'
    var text1 = 'hoge1',
    text2 = 'hoge2',
    text3 = 'hoge3';
    window.addEventListener('DOMContentLoaded', function(e){
    for(var getNum = 1;getNum<=5;getNum++){
    var setText=(typeof this["text"+getNum]!=="undefined")?this["text"+getNum]:"none";
    console.log(setText);
    }
    });

    キャンセル

  • 2018/11/05 18:40

    いろいろありがとうございます。
    スコープの問題でした。

    1点だけ教えて欲しいですが、
    text1~3まで普通の変数なわけですが、this["text"+getNum]で配列になってしまっているのですが、
    これはどういう動きなんですか?
    これでどうして値が取れるのかがどうも理解出来ないです。

    キャンセル

+1

エラーの原因は既出通りですが、try-catch を使用する必要はありません。

console.log(typeof setText !== 'undefined' ? eval(setText) : 'なし');

Re: pinoko さん

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/11/05 20:38

    変数 setText には、'text5' という「変数名」が文字列で入っていて、
    このとき 変数text5が未定義なのかどうかを判定したい、
    という要件のようです。

    すみません、私のコードがgetNum = 3になってます(ました)が、getNum = 5の時の話です。
    修正しておきます。

    キャンセル

  • 2018/11/05 21:08 編集

    変数が未定義なら、typeof演算子は "undefined" を返しますので、そこで判定可能です。
    undefined値とReferenceErrorを区別するなら使えませんが、String値が期待される変数にundefined値を定義済判定するメリットはないと判断しました。

    キャンセル

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

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

関連した質問

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