functionと感嘆符(by葵中剣)


原文の住所:http://swordair.com/function-and-exclamation-mark/
最近暇があったら、心を静めていろいろなコードを見に来てください.functionと感嘆符が頻繁に現れて、2ヶ月前に杭州に帰って最後にチーム会議に参加した時、@西子剣影が投げたような問題:もしfunctionの前に感嘆符をつければ(!)どうなりますか?たとえば、下記のコード:
!function(){alert('iifksp')}() // true 
コンソールが実行された後に得られた値はtrueです.なぜtrueなのかは分かりやすいです.この匿名関数は戻り値がないため、デフォルトではundefinedに戻ります.逆を求める結果は自然とtrueです.したがって、問題は結果の値ではなく、なぜ反作用が匿名関数の自己変調を合法化することができるのかということです.
普段は、括弧を追加して匿名関数を呼び出す方法に慣れているかもしれません.
(function(){alert('iifksp')})() // true 
または:
(function(){alert('iifksp')}()) // true 
上記の2つのかっこの位置は違っていますが、効果は全く同じです.
このような感嘆符の仕方に対して、多くの人が夢中になっているメリットは何ですか?文字を節約するためだけにはあまり必要がないので、100 Kのライブラリを作ってもあまりスペースが節約できないかもしれません.空間ではないなら、まだ時間があるかもしれません.事実ははっきりしないです.文章の最後に性能について言及します.
核心に戻って、なぜこのようにすることができますか?さらに核心的な問題は、なぜこうしなければならないのですか?
括弧にしても、感嘆符にしても、文全体を合法的にすることは一つしかないです.関数ステートメント文を一つの表現に変えました.
function a(){alert('iifksp')} // undefined 
これは関数宣言です.このような声明の後に直接括弧で呼び出すと、解析器は当然理解できず、エラーを報告します.
function a(){alert('iifksp')}() // SyntaxError: unexpected_token 
このようなコードは、関数宣言と関数呼び出しを混同しているため、このように宣言された関数です.  aは  a(); の方式で呼び出します
しかし、括弧は違っていて、関数宣言を式に変換しました.解析器は関数宣言の方式で関数aを処理するのではなく、関数式として処理します.したがって、プログラムが関数aに実行される時だけアクセスできます.
したがって、任意の消去関数宣言と関数表現間の曖昧性の方法は、解析器によって正確に識別されることができる.たとえば:
var i = function(){return 10}(); // undefined 1 && function(){return true}(); // true 1, function(){alert('iifksp')}(); // undefined 
与えられた値、論理、コンマ、各種演算子は、関数宣言ではなく、関数表現であることを、コンフリクトに伝えることができます.また、関数の1元演算を計算すると、曖昧さを解消する一番早い方法です.感嘆符はその中の一つです.戻り値を気にしないなら、これらの1元演算は有効です.
!function(){alert('iifksp')}() // true +function(){alert('iifksp')}() // NaN -function(){alert('iifksp')}() // NaN ~function(){alert('iifksp')}() // -1 
以下のようなキーワードでも、いい仕事ができます.
void function(){alert('iifksp')}() // undefined new function(){alert('iifksp')}() // Object delete function(){alert('iifksp')}() // true 
最後に、括弧でしたことも同じです.曖昧さをなくすのが本当の仕事です.関数を一つの全体としてではなく、括弧を声明に含めても、関数全体を中に含めても合法です.
(function(){alert('iifksp')})() // undefined (function(){alert('iifksp')}()) // undefined 
このように多くのことを言っていますが、実はいくつかの話が最も基本的な概念です.語句、表現、表現語句、これらの概念はポインタとポインター変数のように紛らわしいです.このような混淆はプログラミングに対して特徴付ける影響がありませんが、邪魔者の石はいつでもそのために血が流れます.
最後に性能について議論した.jsperfで簡単にテストを作成しました.http://jsperf.com/js-funcion-expression-speed ,異なるブラウザでアクセスできます.テストを実行して結果を確認します.私も同時に結果を下記の表に並べます.(私は貧しいので、テスト配置が恥ずかしいです.でも、仕方がないです.Pentium双核1.4 G、2 Gメモリ、win 7企業版):
Option
コード
Ops/sec
Chrome 13
Firefox 6
IE 9
Safari 5
!
!function(){}()
3,773,196
10,975,198
572,694
2,810,197

+function(){}()
21,553,847
12,135,960
572,694
1,812,238
を選択します.
-function(){}()
21,553,847
12,135,960
572,694
1,864,155
~
~function(){}()
3,551,136
3,651,652
572,694
1,876,002
(1)
(function(){}()
3,914,953
12,135,960
572,694
3,025,608
(2)
(function(){}()
4,075,201
12,135,960
572,694
3,025,608
void
void function(){;()
4,030,756
12,135,960
572,694
3,025,608
new
new function(){}()
619,606
299,100
407,104
816,903
delete
delete function(){;()
4,816,225
12,135,960
572,694
2,693,524
を選択します.
var i=function(){;()
4,984,774
12,135,960
565,982
2,602,630
&&&
1&function(){}()
5,307,200
4,393,486
572,694
2,565,645
124 124
0|function(){;()
5,000,000
4,406,035
572,694
2,490,128
&
1&function(){}()
4,918,209
12,135,960
572,694
1,705,551
𞓜
1|function(){;()
4,859,802
12,135,960
572,694
1,612,372
^
1^function(){}()
4,654,916
12,135,960
572,694
1,579,778
を選択します.
1,function(){}()
4,878,193
12,135,960
572,694
2,281,186
方式によって生じる結果は違っています.また、ブラウザによって大きく異なります.
でも、私達はやはりその中から多くの共通性を探し出すことができます.new方法は永遠に遅くなります.これも当然です.他の面では差が大きいですが、感嘆符は一番理想的な選択ではないということは確かです.伝統的な括弧を見ると、テストの中ではずっと速く表現されています.ほとんどの場合は感嘆符より速いです.だから、普段使っている方法は大丈夫です.マイナス記号をプラスしてchromeで驚きを表現して、その上その他のブラウザの下でも普遍的にとても速くて、感嘆符の効果よりもっと良いです.
もちろんこれは簡単なテストです.問題を説明することはできません.一部の結論は意味があります.括弧とマイナス記号の中で一番いいです.
しかし、なぜ多くの開発者が感嘆符に夢中になっているのですか?これは習慣の問題だと思いますが、彼らの優劣は全く無視できます.コードのスタイルに慣れると、このような約束はプログラムを混乱から読むことができます.感嘆符に慣れたら、括弧よりもっといい可読性があると認めざるを得ません.読みながら括弧のマッチングに注意しなくてもいいです.編纂中に忘れなくてもいいです.
私もこのようにしていますが、これは意外にも1つの文字を節約して自慢しています.自分が慌てて巻の端にあるC言語の教科書をめくる窮屈さとでたらめさを忘れてしまいました.誰でも忘れた時があります.拾った時には、もう忘れ物だけではありません.
2011-10-31更新:もしatanaを使うなら、(!+-)を使う時に注意してください.これらはatanaの解析を失効させて、Outlineウィンドウは何も表示されなくなります.しかし、コード自体については、実行に問題はありません.