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

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

新規登録して質問してみよう
ただいま回答率
85.48%
プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

JavaScript

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

Q&A

解決済

3回答

3519閲覧

後置演算子の価値とは

aaaaaaaa

総合スコア501

プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

JavaScript

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

0グッド

0クリップ

投稿2015/12/09 11:16

javascript

1 var t = 0; 2 console.log('0',t++); 3 console.log('1',t)

上記の後置演算子は、三行目で1になります。
仕様と言われればそれまでなのですが、なぜ計算前の値を代入してから加算するのでしょうか。
また後置演算子はどのようなときに利用価値を見いだせるのでしょうか。

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

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

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

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

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

guest

回答3

0

ベストアンサー

以下は偏見が混じった非常に個人的な見解です。間違っている可能性もありますので、曇り無き眼で批判的に読むことをお勧めします。


後置であろうが前置であろうがJavaScriptにおいてインクリメント演算子++とデクリメント演算子--不要な物であると考えています。その理由を説明してきます。

JavaScriptでのインクリメント演算子/デクリメント演算子の由来はC言語になると思います(もしかしたら、その前のB言語やBCPLになるかも知れませんが、それらの言語の詳細を知らないため、ひとまずC言語にします)。

C言語が作られた当時、コンパイラを作る技術は未熟でした。コンパイル時の最適化などできるはずもなく、C言語はいかに機械語に翻訳しやすいか(=コンパイラを作りやすいか)を重視して作られました。つまり、C言語の命令と機械語がなるべく1対1になれば、簡単に翻訳できるようになります。たとえば単純に1を足す命令を考えます。その場合、C言語においてもx = x + 1;と書いても問題なく動きます。しかし、この命令は少なくとも「xに1を足す」と「足した値をxに代入する」という二つの命令から成り立ちます。となると、機械語に翻訳したときに少なくとも二つの命令からなります(実際はレジスタへの移動とかありますので、少し異なります)。しかし、ほとんどの機械語にはインクリメント命令とデクリメント命令が用意されていました。単純に1足すだけであればインクリメント命令一つだけで済むはずであり、二つの命令にしなければならないというのは遅くなる原因です。しかし、当時の未熟な技術ではx = x + 1;となっている部分をインクリメント命令に最適化して翻訳することができませんでした。そこで、インクリメントやデクリメントに関しては++--という特別な演算子を別に用意して、プログラマがなるべく速くなるコードを書けるようにしました。(あくまで、私の個人的な見解ですので、間違っているかも知れません。なお、現在のコンパイラは最適化が非常に優秀なため、たぶん、同じコードになることでしょう。)

この伝統のインクリメント演算子/デクリメント演算子はC言語を拡張したC++でも受け継がれました。そして、C++を参考にしてしまったJavaにも受け継がれました。JavaScriptは、その名前にあるとおり、開発の途中で何を血迷ったのかJavaに似せようとしました。JavaにもインクリメントがあるのだからJavaScriptにもあった方がいいだろうという安易な発想の元、インクリメント演算子/デクリメント演算子が実装されました(これも、ただの個人的な見解です)。それが実質ただのx = x + 1にすぎないとしてもです。ご存じの通りJavaScriptはスクリプト言語であり、言語設計において機械語への翻訳を意識する必要はありません。インクリメント演算子/デクリメント演算子を使ったからと言って速くなるわけではないのです(事実、jsperfで確認する限り、速度の違いはほとんどありません)。

つまり、JavaScriptのインクリメント演算子/デクリメント演算子は当時の流行にあやかろうと安易に言語名にまでつけてしまったJavaの弊害であり、C言語からの負の遺産です。事実、言語設計がしっかりした言語、Python、Ruby、Scalaなどはインクリメント演算子/デクリメント演算子は不要であるとし、実装していません(そんなのはx += 1と書けば十分短いし、わかりやすい)。言語的な複雑さを産む(複雑な黒魔術を使いたければ、C++をすればいいのです)ばかりで、速度などと言ったメリットは一切得られないからです。

よって、インクリメント演算子/デクリメント演算子は、JavaScriptの暗黒面、つまり、言語としてとても残念になってしまった部分の一つだと私は考えています。結論としては、利用価値は全くありません。

投稿2015/12/09 12:47

raccy

総合スコア21735

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

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

T.Kanno

2015/12/09 13:01

横レス失礼 個人的には、C言語開発の土壌となった DEC の PDP-11 系のCPUのアドレッシングモードに「プリデクリメント(--i)」と「ポストインクリメント(i++)」があったのがその理由ではないかと思っています。単なる想像ですけど… プリデクリメント
tozjp

2015/12/09 13:16

個人的な見解と強調されていることもあって根拠が弱いですが、説得力はあるというか、共感ができる見解ですね。 機械語の命令数にこだわってコーディングする時代ではないですし、「前置だから/後置だからこの時点では戻り値はいくつで…」なんて考えてないで一旦変数にいれちゃえばいいですし。 もし今実装されてなかったら欲しい機能かと言われると、今さら言語仕様に盛り込むほどのメリットはないですね。
raccy

2015/12/09 13:25

T.Kannoさんが言うとおり、当時のCPUの話だったと私の記憶にもあるのですけど、どこで見たのか覚えていなく、内容も結構朧気なのです。本当はC言語の話とかの根拠資料を用意したかったのですけど、みつけられなかったので、個人的見解ってことにしています。すいません。もし、何か資料を知っている方がいれば、教えていただくとありがたいです。
think49

2015/12/09 13:43

> C言語においてもx = x + 1;と書いても問題なく動きます。しかし、この命令は少なくとも「xに1を足す」と「足した値をxに代入する」という二つの命令から成り立ちます。 x += 1; で一つの命令になるとは考えられないでしょうか。
Chironian

2015/12/09 14:19

こんにちは。 インクリメント/デクリメント演算子の歴史的経緯は、raccyさんやT.Kannoさんの説明に同意です。 ところで、raccyさんも異議が出ることを予想しているっぽいですが、「利用価値は全くありません。」には意義ありです。 「i += 1;」の構文しかない場合、「array[i++]=data;」のような記述ができないので不便です。慣れている人間にとっては「array[i]=data; i += 1;」と書く方がミスしやいです。(タイプ量が多い、文が長い、思考が途切れる。) でも、不慣れな人にとっては逆に「array[i]=data; i += 1;」と書く方がミスしにくいのも事実と思います。 つまり、熟練しないとそもそも使えないC/C++言語ではありがたい存在です。 非熟練者でも使えるよう工夫されたJava系の言語の場合はもしかするとない方が良いのかも知れませんね。
think49

2015/12/09 14:33

個人的な見解としては私も「意義あり」です。 Chironian さんが仰っているケースで i++, ++i を使い分ける事は良くあります。 array[++i] = i; は array[i += 1] = i; とも書けますが、代入文をプロパティや if 文の中に入れるのは分かりやすさの側面から意義を申し立てる人が少なくないと思います。 特に Statement で演算する人にはインクリメントが有効だと思っています。 逆に言えば、Array#forEach 等を関数をよく利用する人にとっては利用機会が少ないかもしれません。 ただ、パフォーマンス目的ではまだ for, for-of にも利用価値があるのでなくなると困るのは事実だと思います。 あと、個人的見解としては関数呼び出しよりも for 文や while 文のような原始的なプログラミングはアルゴリズムが目に見えて分かりやすくて好きです。
Chironian

2015/12/09 15:01 編集

> array[i += 1] = i; とも書けますが うはっ、言われてみればその通りですね。全く思いつきませんでした。 でも、array[--i]は置き換えれないので、より困ったことになりますね。 array[i++]とarray[--i]のようにペアで使うことも多いですから。
think49

2015/12/09 15:13

そうですね。 どちらかといえば、私もループ文では array[i++] を良く使います(index が 0 から始まるというのと while (i < l) の条件式にマッチする為)。
raccy

2015/12/09 15:44

聖典K&R本によると「E1 op= E2 の形の式は,E1が1回だけ評価されるという点を除けば,E1 = E1 op (E2) と同じである。」(p.257)と書いてあるので、`x += 1`は`x = x + 1`と同じになるかとも思います。ただこれはANSI Cの時代の話であり、C11の仕様書みるとちょっと違っているようです。 array[i++]=data;とかの話は言語設計思想の違いじゃないでしょうか。PythonやRubyは「慣れないとわかりにくい」ような書き方はできないようにする傾向があります(Pythonはやり方を強制し、Rubyはやり方を洗脳します)。ついでですけど、私個人としてはC/C++であっても、array[i]=data;i++;としか書かないようにしてます(色々いいながらも、C/C++であれば、インクリメント演算子等を普通に使っちゃってます)。 最後に、私自身、JavaScriptを直接書くことはほとんど無いです。大抵CoffeeScriptかBabelを使ってECMAScript2015で書いています。最近は普通のfor(;;)文を使ったことないので、インクリメント演算子等を必要に思ったことは一度も無かったりします。
aaaaaaaa

2015/12/10 11:02

ご回答有難うございます。 初学者の私でもなんとか理解できましたし、演算子どころか言語の歴史まで知れて大変勉強になりました。 jsも加算減算は、ルビーやパイソンのようにx+=1で十分ということですね。
guest

0

よく誤解されますが、評価してから加算するわけではありません。
加算してから加算前の評価値を返します。

JavaScript

1var array = [1,2,3], 2 i = 0, 3 l = array.length; 4 5while (i < l) { 6 console.log(array[i++]); 7}

Re: aaaaaaaa さん

投稿2015/12/09 11:25

think49

総合スコア18162

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

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

0

連続データをスキャンしたりする時に、利用価値を見出していますが、、、使わないなら使わないなりにすんでしまう機能なので、こだわるほどの事もない気がします。

多分、源流の C言語の出来た経緯によって考案された演算子なのでしょうね。

投稿2015/12/09 11:58

T.Kanno

総合スコア915

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問