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

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

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

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

Q&A

解決済

3回答

2766閲覧

代入しない時の「++a」と「a++」の違い(前置と後置き)

gvaslkjlie

総合スコア4

JavaScript

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

1グッド

1クリップ

投稿2020/07/23 11:20

発生している問題

問題1:代入しない時の「++a」と「a++」の違いがわからない
問題2:値を増加させた時にalertさせるのと、値を増加させた変数をalertすると数が違うのも理解できない。
for文などでは「i++」と、代入しないで増加させることが多い。
for文はよく使うので理解しておきたい。

問題1の検証(前置)

javascript

1var a = 1; 2++a; 3alert(a);//2が表示された。

問題1の検証(後置)

javascript

1var a = 1; 2a++; 3alert(a);//2が表示された。

問題2の検証1

javascript

1var a = 1; 2alert(a++);//1が表示された。

問題2の検証2

javascript

1var a = 1; 2a++; 3alert(a);//2が表示された。

試した事

前置・後置について検索するも、数字を入れた変数に対して、増加させる時に別の変数に代入する場合ばかりで、別の変数に代入させない場合の挙動が不明だった。

Lhankor_Mhy👍を押しています

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

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

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

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

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

guest

回答3

0

ベストアンサー

a++++a は式です。

式と演算子 - JavaScript | MDN

式というのは大雑把に言うと、「評価できる値を持つもの」です。

式 (プログラミング) - Wikipedia

a++ の値は演算する前の a の値で、++a の値は演算する前の a の値に 1 を加えたものです。
++ は前置後置のどちらも a の値を 1 増やすという副作用を持ちます。
副作用とは、式の値と無関係に何か状態を変化させるもののことです。

副作用 (プログラム) - Wikipedia

つまり、代入や演算など式として評価した際には前置と後置は違う値を示しますが、その副作用は変数の値を 1 増やすという同じものです。

値は違うけれども副作用は同じなので、値を考えない場合、この二つは同じものであるといえます。for (let i = 0; i < 10; i++) の場合、i++ の値は捨てられています。よって副作用のみが意味を持つため、この場合前置と後置は同じものと言えます。

投稿2020/07/23 11:37

編集2020/08/08 02:15
Zuishin

総合スコア28669

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

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

gvaslkjlie

2020/07/23 11:52

ご回答ありがとうございます。質問文「問題2の検証1」では、演算する前の a の値である「a++」をalertしたので「1」が出力されたことは理解できました。質問文「問題2の検証1」で最後に「alert(a);」を実行すると、副作用で1増えた「2」が出力されたことも確認できたので質問文「問題2の検証1」の挙動は理解できました。「問題2の検証2」についてもZuishin様のご回答の読解をして理解しようと思います。少しお時間をいただきます。
Zuishin

2020/07/23 11:56

> 問題2の検証2 a++ の副作用によって a の値が 1 増えた後に alert が呼ばれています。呼ばれた時にはすでに 2 になっているので 2 が表示されます。
gvaslkjlie

2020/07/23 12:11

挙動についての解釈は下記でよろしいでしょうか? --------------- 質問文「問題2の検証2」においては「a++;」が実行されたが、 演算する前の a の値なのでこの時点では1である。 直後に副作用が起きaが1増えたので、次の行のalertで「2」が出力された。 副作用は次の命令文から反映されるものであるため 「問題2の検証1」のalert時には 副作用が反映されていない「1」が出力された。 もし末尾に「alert(a);」という次の命令文を追記すると、 副作用が反映された状態の「2」が表示される。
gvaslkjlie

2020/07/23 12:13

副作用が反映されるタイミングの解釈に自信がもてないです。。。
gvaslkjlie

2020/07/23 12:15

それとも 誤:副作用は次の命令文から反映される 正:副作用は式実行直後に反映される でしょうか?
gvaslkjlie

2020/07/23 12:32

何度もすみません。最初にいただいたご回答の副作用のwikipediaに「それ以降で得られる結果に影響を与える」とありましたので、副作用が反映されるタイミングについても理解ができました。wikipediaを見落としていました。失礼いたしました。
Zuishin

2020/07/23 12:50

副作用については同時と思ってください。直後の方がわかりやすければ直後と思ってもかまいません。 たとえば次のような関数があったとします。 const func = array => { const result = array.length; array.unshift('a'); return result; }; これを次のように呼び出します。 const sampleArray = ['a', 'b', 'c']; console.log(func(sampleArray)); console.log(sampleArray); この結果は次のようになります。 3 [ 'a', 'a', 'b', 'c' ] つまりこの関数は、呼び出すと、引数として与えた配列の要素数を値として返し、要素を一つ増やす副作用を持つものです。 要素数は関数実行後には 4 つになっているため、この直後に console.log(sampleArray.length); を実行すると 4 と表示されますが、関数の返した値は 4 ではなく 3 です。 この関数の場合、副作用は値を評価するより前に生じていますが、副作用が生じるのが値の評価直後であると認識しても、それほど問題はありません。
gvaslkjlie

2020/07/23 13:52

ご回答ありがとうございます。 「func関数の返した値は 4 ではなく 3 」とのことですが、func関数がreturnした定数resultの値はunshiftする前に設定されているので3なのは当然のような気がします。 unshiftした後の値をrerturnすように変更するとどうなるか下記のようにテストしました。 const func = array => { array.unshift('a'); const result = array.length; return result; }; const sampleArray = ['a', 'b', 'c']; alert(func(sampleArray)); alert(sampleArray); すると、func関数の戻り値は4となりました。このテストでZuishin様のおっしゃる通り、unshiftの要素を一つ増やす副作用は配列の要素数を値として返す前に生じていることがわかりました。このことから、unshiftの場合は前、インクリメント演算子の場合は後といったように、副作用は同時ではない気がしてきました。前と後で結果が変わってしまった問題2の検証のようなケースがあるので、副作用のタイミングが前か後か同時かはっきりさせたいと思っております。
Zuishin

2020/07/23 14:08 編集

インクリメントもマシン語レベルで見ればこのような値の保存が行われています。JavaScript レベルではこれ以上に処理を分割できないので、実際の処理が前であろうと後であろうと何も変わりませんから、確かめようがなく、時には同じコードで順序が逆転する事もあるでしょう。だから考えなくても大丈夫です。
gvaslkjlie

2020/07/23 14:20

ご回答ありがとうございます。「実際の処理が前であろうと後であろうと何も変わりません」とのことですが問題2の検証1と検証2では出力が変わってしまっています。問題2の検証1のようにいきなり出力をせずに、問題2の検証2のように次以降の処理で出力すれば、常に同じ結果が得られますでしょうか?
Zuishin

2020/07/23 14:31

では、表現を変えましょう。先に書いたように、評価と副作用は同時です。問題 2 は評価が a++ と a の複数回行われているので検証として無意味です。次の評価の前には前の式の副作用は終わっています。
Zuishin

2020/07/23 14:38

例えば関数呼び出しも式です。先ほど示したように、関数が呼び出されて戻り値が評価される頃には副作用は終わっています。この場合、評価後に副作用を生じさせることはできません。しかし値は前もって保存されたものが返るので元の値として評価されます。 同様にインクリメントも、値を保存した後で副作用を生じさせ、保存したものを返すのが合理的ですが、それは JavaScript レベルでは一つの処理で分割できないので、前も後もありません。
Zuishin

2020/07/23 14:39

要するに a++ の値は a の値ではなく、あくまで a++ という式(関数呼び出しのようなもの)の値ということです。
gvaslkjlie

2020/07/23 14:54

ご回答ありがとうございます。参考URL先のページを読んでみようと思います。理解に時間がかかりそうなのでしばらくお時間いただきます。拙い質問にお付き合いくださりありがとうございました。
Zuishin

2020/07/23 15:05

JavaScript には参照渡しが無いので書きにくいのですが、後置インクリメントは次のように書けます。 let a = 3; const plusplus = () => { const result = a; a = a + 1; return result; }; この場合、関数の戻り値は 3 です。しかし、関数終了後、a は 4 になります。この関数は値が a の元の値で、副作用が a に +1 すること、つまり a++ と同じ処理をします。 では評価と副作用の順番を見てください。評価は関数が終わってからなので、副作用の方が先ですね? しかし、副作用が終わっているにもかかわらず、戻り値は a の元々の値に等しくなります。 この関数がブラックボックスでこれ以上分割できない時、評価と副作用はどちらが先でも実用上何の違いもないわけです。ということは、実際の処理に合わせて順序を最適化してもいいわけです。結果は同じです。
gvaslkjlie

2020/07/23 16:04

ご回答ありがとうございます。いただいたコメントの文章「評価と副作用はどちらが先でも実用上何の違いもない」の"評価"を下記の「評価B」、"副作用"を下記の「副作用A」として解釈してみました。 ------------ let a = 1; alert(a++); ------------ とした時に下記1〜3の順序で処理される。 順序1:a=1を評価(aに1を代入) ↓ 順序2:a++を評価(下記[2-1]〜[2-2]の順で処理)  [2-1]・・・aの値を保管  ↓  [2-2]・・・下記「副作用A」と「評価B」を"同時"に実行  副作用A=aの値を「[2-1]で保管した値に1加算した値」に変更する  評価B=「[2-1]で保管した値」を返す(alertの引数となる) ↓ 順序3:alert(1)を評価(1が出力される) ------------ 結論:上記「副作用A」と「評価B」はどちらが先でも結果は変わらないので気にしなくていい。
guest

0

問題1:どっちも一緒。悩まんでもよろしいです

投稿2020/07/23 11:25

y_waiwai

総合スコア88042

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

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

gvaslkjlie

2020/07/23 11:29

ご回答ありがとうございます。「別の変数に代入しない場合」は同じ挙動ということでしょうか?
y_waiwai

2020/07/23 11:32

そういうことですね。 文の中にそれが記述してある場合は、 ++x  xを+1してから文を実行 x++ 文を実行してから xを+1 という動作になります
gvaslkjlie

2020/07/23 11:37

ご回答ありがとうございます。問題1の検証で結果に違いがなかったことは気にしないことにします。ありがとうございました。
guest

0

どっちも同じです。

  • 中身を評価してから、加算(a++)
  • 加算してから、評価(++a)

評価結果を使えば、違いますが、使っていないので。
お好きな方を。(以前、宗教論争があった気もするが、良く知らない)

投稿2020/07/23 11:25

pepperleaf

総合スコア6385

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

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

gvaslkjlie

2020/07/23 11:32

ご回答ありがとうございます。ここでいう「評価」とは何のことでしょうか?
pepperleaf

2020/07/23 11:32

あっと、Javaのつもりで書いて書いていましたが、Javascriptでも同じようですね。ちょっと焦った。。。
pepperleaf

2020/07/23 11:45 編集

前置/後置した式の結果の取得。 Zuishinさんの回答が詳しいでしょうか。 --- 以下、誤り -- 「評価」とは、変数の中身の取得です。変数にしか使えないので、ちょっと適切でなかったかも。
Zuishin

2020/07/23 11:49 編集

コメント削除
gvaslkjlie

2020/07/23 11:55

ご返信ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問