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

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

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

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

Q&A

解決済

2回答

3390閲覧

input type="file" multiple でuploadする度に変数をカウントアップさせる

pegy

総合スコア243

JavaScript

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

0グッド

0クリップ

投稿2017/10/10 10:30

編集2017/10/10 10:43

複数のファイルをアップロードすることを許可しているのですが、アップロードされている
ファイルをタイムリーにカウントしようとしております。
そこで、アップロードされる度にそのファイル個数(files.length)を変数に加算するために
file_length+=element.files.length;
としているのですが、NaNが返ってきてしまいます。
+=の加算代入演算子の使い方が誤っているのでしょうか?
よろしくお願いいたします。

Javascript

1<input type="file" id="files" style="display: none" value="2097152" name="file" multiple /> 2<script type="text/javascript"> 3 var element=document.getElementById('files'); 4 var file_length; 5 $(function(){ 6 $('#files').on('change',function(){ 7 file_length+=element.files.length; 8 console.log(file_length); 9 }) 10 11 }); 12 </script>

[加筆]
ローカルスコープからグローバルスコープの変数に加算代入演算したいということになりますが、
そもそも不可能なのでしょうか? スコープの問題もありますが、なぜNaNが返ってくるのかわかりません。。

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

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

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

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

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

guest

回答2

0

ベストアンサー

変数宣言時にfile_lengthに値を代入していないからではないでしょうか?

var file_length = 0;とするべきです。

[加筆]に対し追記:

javascriptの場合、外側で宣言した変数は特に何も気にすることなくグローバル変数として使用できたはずです。

追記:

繰り返しになりますがpythonじゃあるまいし(pythonの場合はglobalの明示が必要)ローカルスコープでグローバル変数が使えないなんて事は無いですよ?

サンプル

もしずっと0なのでしたら、そもそもelement.files.lengthの値が0だったりしませんか?

ちなみに実行タイミング的にconsole.log(file_length);//ここのグローバル変数を加算していきたい!における出力は0が正しいです。

さらに追記:

ローカルで変化した変数をグローバルで参照したい

とのことですが、今回の処理の場合は全部グローバル変数で管理する方がいいと思いますよ?

関数内でvarを使ってローカル変数を宣言された場合、関数を抜けた段階で値がリセットされてしまいますから、そもそもローカル変数に値を保存するということ自体がまず不可能です。

javascript

1var glbl; 2 3var lcl = function(n){ 4 var val = 0; 5 // ↑ここで0を代入してしまっている時点で、、あっ、ふ〜ん(察し)という感じですが(^ ^; 6 // しかし入れないわけには行きません。 7 val += n; 8 console.log(val); 9 10 glbl = val; // 質問者様が行いたいと考えておられること 11} 12 13lcl(10); // 期待する値 : 10 実際 : 10 14console.log(glbl); // 期待する値 : 10 実際 : 10 15lcl(10); // 期待する値 : 20 実際 : 10 16console.log(glbl); // 期待する値 : 20 実際 : 10 17lcl(10); // 期待する値 : 30 実際 : 10 18console.log(glbl); // 期待する値 : 30 実際 : 10

ですから関数内でもグローバル変数のみを用いる、という方法のままでいいと思います。

その直後(グローバル変数に保存した直後)にelement.files.lengthで得られた値を使って別な処理をしたいわけでも無い限り、使い捨てのローカル変数を用意するだけ無駄です。

どうしてもスコープを意識したいのであればオブジェクト指向の考え方を使い、インスタンスのプロパティに保存すれば意図した動作となるとは思いますが、今回の動作でそのような大掛かりなものは不要だと思われます。

html

1<button>btn</button> step : <input type="number" value="10" /> 2<script> 3$(function(){ 4 var glbl = 5; 5 6 var lcl = new (function(){ 7 this.step = 10; 8 this.add = function(){ 9 glbl += this.step; 10 alert(glbl); 11 }; 12 })(); 13 14 $("button").click(function(){lcl.add();}); 15 $("input").on("change",function(e){ 16 lcl.step = parseInt(e.target.value); 17 }); 18}); 19</script>

サンプル

上記サンプルでは足していく値(step)をオブジェクト内に保存しています。

私の方こそ質問をよく理解していないかもしれません。。もし欲しい答えでなければすみません。。m(_ _)m

ようやく質問者様のおっしゃりたいことがわかってきたような気がするので改めて追記させてください。

当然グローバルでは加算されていないため、0が出力されてしまいます。

違います。ローカルスコープにおいてすでに参照されている変数はグローバル変数ですから、changeイベントが行われたあとにはちゃんとグローバル変数であるfile_lengthに新しい値が代入されています。

しかしながらconsole.log(file_length);//ここのグローバル変数を加算していきたい!はそもそも**changeイベントが行われた後には実行されません**。

このコードが実行されるのは**changeイベントのリスナーをinput要素に付与した直後のみ**ですから、0が出力されるんです。先ほど「ちなみに」として発言したのはこれをさしてのことです。

決してグローバル変数の値が更新されないから0が出力されるのではありません。

むしろ//console.log(file_length); ここじゃない!が正しい変更後の値を示す場所です。ここで出力される値はグローバル変数のものです。ローカル変数ではありません。

証拠としてもう一つサンプルを挙げようと思います。

html

1<input type="text" /> <button>hogeの中身</button> 2<script> 3var hoge = ''; 4 5$(function(){ 6 $('input').on('change',function(e){ 7 hoge = e.target.value; 8 console.log('ここじゃない!の場所 : ' + hoge); 9 }) 10 console.log('ここのグローバル変数を加算していきたい!の場所 : ' + hoge); 11}); 12 13$(function(){ 14 $('button').click(function(){ 15 console.log('ちゃんとグローバルに保存されている : ' + hoge); 16 }); 17}); 18</script>

サンプル

サンプルを試していただければわかると思いますがconsole.log(file_length);//ここのグローバル変数を加算していきたい!に当たる場所は最初に一回実行されているだけです。

追記のために非常に長くなってしまいました。。すみません。。

不明点等あればまた返信ください。m(_ _)m

投稿2017/10/10 10:41

編集2017/10/10 15:57
namnium1125

総合スコア2043

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

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

pegy

2017/10/10 10:53 編集

早速コメントありがとうございます。 初期値は勝手に0とJavascriptが判断してくれると誤解しておりました。 undefined+number=NaNということでしょうか。 本件はおかげ様で理解することができたのですが、 スコープの問題として、ローカルスコープでグローバルスコープの変数に加算代入演算したい場合も あるかと想像しているのですがその様なことも可能なのでしょうか? 下記の様な方法です。当然グローバルでは加算されていないため、0が出力されてしまいます。 重ねてで誠に申し訳ございませんが、ご教示いただけましたら幸いです。 <script type="text/javascript"> var element=document.getElementById('files'); var file_length = 0; $(function(){ $('#files').on('change',function(){ file_length+=element.files.length; //console.log(file_length); ここじゃない! }) console.log(file_length);//ここのグローバル変数を加算していきたい! }); </script>
namnium1125

2017/10/10 11:07

追記しました。よろしくお願いします。m(_ _)m
pegy

2017/10/10 11:15

初心者の私にお付き合いをいただき申し訳ございません。。そしてありがとうございます。 >ローカルスコープでグローバル変数が使えないなんて事は無いですよ これはローカルスコープからグローバルスコープの変数を参照することができるということかと理解しております。ご作成いただいたサンプルもグローバルの10を参照してローカル上で5を加算しているという意図でご用意いただいたのかと思います。 質問の意図としては反対でローカルで変化した変数をグローバルで参照したいということです。 >console.log(file_length);//ここのグローバル変数を加算していきたい!における出力は0が正しいです。 まさにここの部分なのですが、グローバルスコープ上の変数でもファイル数のカウントアップの状態を管理したく、0ではなくカウントアップした数が代入されてほしいということになります。 意図をうまく伝えることができずに申し訳ございません。。
namnium1125

2017/10/10 13:04

追記しました。よろしくお願いします。m(_ _)m
namnium1125

2017/10/10 15:40

さらにまた追記しましたので、よろしくお願いします。m(_ _)m
pegy

2017/10/11 01:14

namnium1125様 詳細なサンプルまで有難うございます!大粒涙付きの感謝です。。。 最後のサンプルでいうところの print('ここのグローバル変数を加算していきたい!の場所 : ' + hoge); という箇所が「イベントが行われた後には実行されません。」ということなのでしょう。 これが実行される時点ではhogeには何も格納されていないため、 「ここのグローバル変数を加算していきたい!の場所 : '」が1度しか表示されないことが 仰りたい意味かと理解しました。 changeイベントやclickイベントの外なので、当然といえば当然なのかもしれませんが。。。 一度グローバルスコープで宣言し、ローカルスコープから参照した変数についてはローカル内での処理で影響を与えることができるのですね。。誤解をしておりました。 少し内容を変えて hoge+=(e.target.value)|0; としてみましたが、グローバル変数hogeに影響を与えていることを確認しました。 https://jsfiddle.net/mcLsarpy/2/ ただ、なぜか加算代入演算子中では|0をしてもNumber()でも文字列から変わらずに 連結されてしまいます。。。
namnium1125

2017/10/11 04:51

?ビット論理和を出してどうするのでしょうか??ごめんなさい私の方が無知なのかも… もし3項演算子のつもりでしたら、 javascriptの3項演算子は`変数 = 条件 ? trueの時 : falseの時;`です。 こういうことがしたかったのでしょうか? https://jsfiddle.net/mcLsarpy/5/
pegy

2017/10/11 06:40 編集

コメント有難うございます! 結果としてやりたかったことはまさに提示頂いたとおりなのですが、だ 加算代入演算(a+=c ⇒a=a+c)を使えば、 element.files.length;でファイル数を取得するたびにグローバル変数file_lengthに数値が加算されるかと 想像したのですが、(つまりアップロードされたファイル数をカウントできる。multipleなので1ずつ加算はできないので) つまりa =file_length で c=element.files.length;ですね。|0は数値型への変換です。 ご提供の3項演算子と同じ結果が得られると思ったのですが、加算代入演算子を使用するとどうしても文字列になってしまいます。 すみません、もとの質問の趣旨からはかなりそれてしまいますが。 基本的な部分は殆ど解決したのでnamnium1125先生に心から感謝です!
pegy

2017/10/11 15:32

すみません、こちらこそ凡ミスで申し訳ございません。 今回の質問で初心者ながら、1レベルアップしたと思っています。 回答者様に本当に深謝でございます。 また、こんな有意義な場を提供してくれる、teratailは素晴らしい! 改めて有難うございました。
guest

0

formdataでテスト

javascript

1$(function(){ 2 var file_length = 0; 3 $('input[type=file]').on('change',function(){ 4 if($(this).closest("form").length==0){ 5 $(this).wrap("<form>"); 6 } 7 var fd=new FormData($(this).closest("form").get(0)); 8 file_length+=fd.getAll($(this).attr("name")).length; 9 console.log(file_length); 10 }); 11}); 12

HTML

1<input type="file" name="f1" multiple /> 2<input type="file" name="f2" multiple /> 3<input type="file" name="f3" multiple />

投稿2017/10/10 11:58

yambejp

総合スコア114839

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

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

pegy

2017/10/11 08:47

コメント有難うございます。 カウント加算させるための違うアプローチとしてコードを勉強させて頂きます。
yambejp

2017/10/11 08:58

挙動が想定と合致しているかだけ確認しておいて下さい。 FormDataはフォーム系処理をする場合あらゆる場面で使用されるものなので 覚えておいて損はないでしょう
pegy

2017/10/11 15:36

フォーム関連の処理でformDataオブジェクトは使ったことがなかったです。早速学びに取り掛かります。貴重な情報を提供頂き、有難うございます
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問