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

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

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

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

Q&A

解決済

5回答

1626閲覧

Javascriptのクロージャに関する初歩的な質問

退会済みユーザー

退会済みユーザー

総合スコア0

JavaScript

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

0グッド

3クリップ

投稿2016/02/23 03:32

編集2016/02/23 03:38

閲覧ありがとうございます。
Javascriptのクロージャーについての基本的な疑問があります。

var countUpFromZero = function() {
var count = 0;
return function() {
console.log(count);
count += 1;
}
}();

countUpFromZero(); //0を出力
countUpFromZero(); //1を出力
countUpFromZero(); //2を出力

上記は基本的なクロージャだと思います。

質問の内容は以下の通りです。
countUpFromZero()を処理するたびに、var count = 0で初期化されているのに、出力結果が1ずつ増えていくのはなぜなのでしょうか?

このような質問をしている時点で私はクロージャをよく理解していないと思いますが、なんとか理解したいと思っています。
一応、javascriptのスコープチェーンとレキシカルスコープの基本的な点は理解しているつもりです。

回答宜しくお願いします。

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

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

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

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

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

guest

回答5

0

ベストアンサー

説明の為に関数名を付けます。

JavaScript

1'use strict'; 2var countUpFromZero = function parent () { 3 var count = 0; 4 return function countUpFromZero () { 5 console.log(count); 6 count += 1; 7 } 8}(); // 即時関数式で関数を即座に呼び出す為、変数 countUpFromZero には function countUpFromZero が格納される 9 10countUpFromZero(); // 0 を出力 11countUpFromZero(); // 1 を出力 12countUpFromZero(); // 2 を出力

コメントに書いたように、**「変数 countUpFromZero には function countUpFromZero が格納」**されます。
関数 parent で宣言された変数 count はスコープチェーンの規則によって function countUpFromZero から参照可能ですが、この変数は function parent 内に閉じ込められます。
従って、countUpFromZero() が呼び出される為に function parent スコープ内の変数 count を参照し、インクリメントし続ける事になります。

Re: tetsu95 さん

投稿2016/02/23 03:42

think49

総合スコア18162

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

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

退会済みユーザー

退会済みユーザー

2016/02/23 04:28

回答ありがとうございます。 変数countUpFromZeroにはreturnの内容である関数が格納されるのは理解できます。 私が考えているのは以下の通りです。 1回目のcountUpFromZeroが実行されると、var count=0が実行され、次にreturn文が処理され、変数countUpFromZeroに関数countUpFromZeroが格納される。 そしてconsole.log(count)で外側の関数にあるparentへの参照を獲得して0を出力する。 2回目のcountUpFromZeroの実行の際もvar count = 0が実行されると思う(ここが間違っているのかもしれません)ので、2回目以降も0を出力するのではないのか?ということを思ったのです。 出力結果から考えて間違っているのは私なのですが、納得がいかないのです。
think49

2016/02/23 04:36 編集

var count = 0; が実行されるのは function parent が呼び出された時ですが、これは変数 countUpFromZero への格納時に既に終わっています。 countUpFromZero(); で実行されるのは function countUpFromZero であり、function parent は呼び出していません。 従って、countUpFromZero(); で呼び出されても var count = 0; は実行されません。
退会済みユーザー

退会済みユーザー

2016/02/23 04:43

回答ありがとうございます。 var count = 0; の実行タイミングを誤解していたようでした。 おかげさまで納得できました! ありがとうございます!
guest

0

みなさんの言う通りです。
想定している動きをするのは以下のようなコードですね。

javascript

1var countUpFromZero = function() { 2 var count = 0; 3 return function() { 4 console.log(count); 5 count += 1; 6 } 7}; 8 9// 毎回0と表示 10countUpFromZero()();

投稿2016/02/23 04:38

編集2016/02/23 04:39
root_jp

総合スコア4666

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

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

退会済みユーザー

退会済みユーザー

2016/02/23 04:46

回答ありがとうございます。 提示していただいたコードと、質問内で私が提示したコードの差異を確かめることでよく理解できました!
guest

0

クロージャというよりも文法を勘違いされているかもしれません。
関数の後ろにかっこをつける書き方は、関数に引数を渡して即実行するものです。

javascript

1var x = function(n){ 2 return n; 3}(0); 4//x=0

ですので、御質問のコードの外側の関数はその場で実行されますから、countUpFromZeroに代入されるのはその結果です。

投稿2016/02/23 03:47

Lhankor_Mhy

総合スコア36057

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

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

退会済みユーザー

退会済みユーザー

2016/02/23 04:47

回答ありがとうございます。 関数の即時実行の書き方と適切な使い方についても調べてみようと思いました!
guest

0

countUpFromZero()を処理するたびに、var count = 0で初期化されているのに

されていません。

countUpFromZeroに代入されているのは、無名関数がreturnで返すfunction() {console.log(count);count += 1;} です。

投稿2016/02/23 03:44

otn

総合スコア84489

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

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

退会済みユーザー

退会済みユーザー

2016/02/23 04:44

回答ありがとうございます。 var count = 0; の処理タイミングを誤解していたことに気付きました!
guest

0

こっちの方が理解しやすいと思います。
countとfunc変数を初期化+定義した後に、戻り値としてfunc変数を返す。
…という内容の即時実行関数を実行しているわけです。

var countUpFromZero = function() { var count = 0; var func = function() { console.log(count); count += 1; } return func; }();

countUpFromZero(); を叩くと下記の部分しか実行されません。
count変数を初期化している箇所は何処にもありません。

console.log(count); count += 1;

投稿2016/02/23 04:57

miyabi-sun

総合スコア21158

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

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

guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問