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

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

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

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

Monaca

「Monaca」はiOS、Android、Windows向けのアプリ開発に対応した、Cordovaベースのモバイルアプリ開発プラットフォームです。HTML5、JavaScriptといったWeb標準技術を用いてモバイルアプリ開発を行うことができます。

Q&A

解決済

1回答

325閲覧

letで宣言した変数がスコープ内で参照できません。

nikkori

総合スコア20

JavaScript

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

Monaca

「Monaca」はiOS、Android、Windows向けのアプリ開発に対応した、Cordovaベースのモバイルアプリ開発プラットフォームです。HTML5、JavaScriptといったWeb標準技術を用いてモバイルアプリ開発を行うことができます。

0グッド

0クリップ

投稿2019/01/31 04:27

編集2019/01/31 05:03

前提・実現したいこと

letで宣言した変数がスコープ内で参照できません
他のletで宣言した変数は利用できるのですが理由を知りたいです。

発生している問題・エラーメッセージ

ReferenceError :Can't find variable:startTime

該当のソースコード

JavaScript

1{ 2 let timer = document.getElementById('timer'); 3 let start = document.getElementById('start'); 4 let stop = document.getElementById('stop'); 5 let reset = document.getElementById('reset'); 6 7 let startTime;// setTimeout内の関数でなぜか呼べない 8 let elapsedTime = 0; 9 function countUp(){ 10 setTimeout(function(){ 11 elapsedTime = Date.now() - startTime; 12 console.log(elapsedTime); 13 countUp(); 14 },10); 15 } 16 start.addEventListener('touchstart',function(){ 17 startTime = Date.now(); 18 countUp(); 19 }); 20}

試したこと

  • startTimeをvarにすればできる
  • elapsedTime はletのままでもOK
  • addEventListenerの時点ではstartTime はとれている(console.logで確認)
  • startTimeを0で初期化してもNG
  • 変数名を変更(startTime→aaa等)にしてもNG
  • エラー箇所はデバッグログの行番号で特定済み

補足情報(FW/ツールのバージョンなど)

monacaで開発中
JavaScript初心者です。
varを使えばできるのですが、他の変数はletを使っているのでできればそろえたくて・・・。

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

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

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

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

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

dice142

2019/01/31 04:29

エラー文およびソースコードは実際のもののコピペですか? それとも投稿時に実際のものを見ながら手打ちしましたか?
nikkori

2019/01/31 04:30

コピペしたものにコメントを加えました
nikkori

2019/01/31 04:30

あ、すみません、エラー分は手打ちです。
papinianus

2019/01/31 04:33

仕様を確認したわけではないですが、letで参照できず、varで参照できることが、スコープ外ということの意味じゃないかと思うのですが。
dice142

2019/01/31 04:33

エラー文もコピペのほうが良いです。 というのも読み間違えて打っていたら解決が困難になるからです。 ソースコード同様にコードブロックで囲んでもらえると見やすいです。
nikkori

2019/01/31 04:36

>dice142さん すみません、MonacaというクラウドIDEではデバッガーのエラーログがコピペできないので… 方法はあるのかもしれないので別件で調べてみます。
nikkori

2019/01/31 04:38

>papinianusさん そうおもったのですが…おなじスコープで宣言している変数(elapsedTime )が参照できるのに startTimeは参照できないんです。。。setTimeoutという関数がなにか特殊なスコープを持っているとかなんでしょうか・・・
dice142

2019/01/31 04:40

ちなみに提示されたコードをコピペして(呼び出し部分だけ外に出して)やってみましたが、正常に動作しました。
dice142

2019/01/31 04:48

後は本当にエラーの箇所がそこなのかも確認したほうが良いかと思います。 (本当は他でstartTimeを使っていてそこだったとか。)
nikkori

2019/01/31 04:48

elapsedTime = Date.now() - startTime; ↑この部分を外に出してということでしょうか?
nikkori

2019/01/31 04:51

コピペはできないのですが、デバッガにでている行番号からこの箇所であることは特定しています。 サンプルソースにちかいものなので、ソースもこれでほぼすべてです。。。
dice142

2019/01/31 04:52

start = addEventListener(... の以下の部分です。 === startTime = Date.now(); countUp(); === startという変数がなかったので、とりあえず呼び出せるように外に出して確認しただけですね。
nikkori

2019/01/31 04:53

ちなみに元ソースはドットインストールの 「 JavaScriptでストップウォッチを作ろう #03 カウントアップ機能を実装しよう」 https://dotinstall.com/lessons/stop_watch_js_v4/41203 です。 varではなくなるべくletを使うようにしていたので、変更して記載したらエラーになりました。
dice142

2019/01/31 04:54

> コピペはできないのですが、デバッガにでている行番号からこの箇所であることは特定しています。 通常のJSではできているので、環境の問題でしょうかね。
papinianus

2019/01/31 04:57 編集

> おなじスコープで宣言している変数(elapsedTime )が参照できる おっしゃるとおりですね。他にstartTimeがいないですかね。もしくはlet startTime = 0;とする。 (もしくはの意図は、宣言のみで代入がないので、最適化の都合などで省略された可能性を想定してます) もしくはstartTimeは変動するものではないので、みんなletだからletじゃなくて、宣言時に`const startTime = Date.now()`とする
nikkori

2019/01/31 04:57

>startという変数がなかったので 失礼しました。ソース修正しました。 >通常のJSではできているので、環境の問題でしょうかね。 ありがとうございます。 環境の問題であれば、あきらめてvarで書くことにします。 まだJSソースを見慣れていないので、なにか見落としているのかと悩んでいました。 助かりました!!
nikkori

2019/01/31 04:59

>papinianus ありがとうございます。初期化はいま試したみましたが、同じ結果でした。。 開発環境がちょっと特殊(Monaca)なので、環境の問題のような気がします。
papinianus

2019/01/31 05:01

環境が無関係だとは思いませんが、ご自身で書いた、elapsedがいけて、startができないは環境ではないと思いますが… ブロックスコープが作用するブロック全体を提示して、有識者をまつ、が妥当だと思います。
nikkori

2019/01/31 05:02

ソースコードを修正してみます。ありがとうございます。
nikkori

2019/01/31 05:12

一番外側の{}を外したら動きました・・・ 理由はよくわからずにおまじない的にいつも{}を付けていたのですが… とりあえず自己解決のところに書いてみます。
papinianus

2019/01/31 05:14

分かりました。 {}はブロックスコープをつくります。従って、let startTimeはglobalじゃなくてその無名の{}の中にしか存在しません。 startTime = Date.now(); のstartTimeや elapsedTime = Date.now() - startTime; のelapsedTimeでエラーが起こらないのは、その場で変数宣言が起きているからです。(elapsedTime = Date.now() - startTimeの直前にconsole.log(elapsedTime);とするとエラーになるはず)
nikkori

2019/01/31 05:26

>その場で変数宣言が起きているから startTime = Date.now(); こういう書き方をすると暗黙的に変数が宣言されるということなのでしょうか・・・? 全然知りませんでした。勉強不足なので自分でも調べて理解してみます。 でも、解決の道が見えました!ありがとうございます。
papinianus

2019/01/31 05:32 編集

いますぐブラウザのF12を押してコンソールに`neverexists = "somestring"`とやってエラーが**起こらない**ことを確認しましょう。宣言したことになります。
nikkori

2019/01/31 05:42

>`neverexists = "somestring"` こちらではうまく動かずでした。クラウドIDEでスマホのハイブリッドアプリを作っているので ブラウザで確認できないのです…ややこしくてすみません ただ、理由がわかったので自分で調べてみようと思います。 ベストアンサーを付けたいのですが、どうすればいいでしょうか?(初めての質問で勝手がわからず)
papinianus

2019/01/31 05:46 編集

私のコメントは{}を外した理由の説明でしかないので、{}をはずしたら動きましたの自己解決でいいと思います。
nikkori

2019/01/31 05:52

ありがとうございます。自己解決欄に記載します。 おまじないの部分もきちんと理解して書かなきゃですね。。
nikkori

2019/02/01 00:12

ありがとうございます・・! 記事読みました。理解できてきたので、実際に試しながら使い方をマスターしていきたいです!
guest

回答1

0

自己解決

一番外側の{}をはずしたら解決しました。
以下、papinianusさんからのコメントでいただいた内容です。

{}はブロックスコープをつくります。従って、let startTimeはglobalじゃなくてその無名の{}の中にしか存在しません。

startTime = Date.now();
のstartTimeや
elapsedTime = Date.now() - startTime;
のelapsedTimeでエラーが起こらないのは、その場で変数宣言が起きているからです。(elapsedTime = Date.now() - startTimeの直前にconsole.log(elapsedTime);とするとエラーになるはず)

私の場合、(function(){})();で書くところを、深く考えず{}にしていたのがNGだったようです。
意味を理解して書こうと思います。

投稿2019/01/31 05:54

nikkori

総合スコア20

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問