今回は、jsの(function(){xxx})()の使い方について詳しく説明します。jsの(function(){xxx})()を使用する際の注意事項は次のとおりです。場合は、見てみましょう、見てみましょう。
自己実行匿名関数:
共通形式: (function() { /* code */ } ) ();
説明: 関数を囲む最初の括弧のペア (function(){}) は、名前のない関数をスクリプトに返し、次に空の括弧のペアは、返された名前のない関数をすぐに実行します。括弧は匿名の関数のパラメータです。
関数: これを使用して 名前空間 を作成できます。この特別な関数パッケージ内にすべてのコードを記述する限り、許可しない限り、外部からアクセスすることはできません (変数なので、関数または変数はグローバルになります)。各 JavaScript ライブラリのコードは、基本的にこのように編成されています。
要約すると、実行関数の主な機能は匿名と自動実行です。コードは解釈された時点ですでに実行されています。
その他の書き方
<span style='font-family: 微软雅黑, "Microsoft YaHei"; font-size: 14px;'>(function () { /* code */ } ()); <br>!function () { /* code */ } ();<br>~function () { /* code */ } ();<br>-function () { /* code */ } ();<br>+function () { /* code */ } ();</span>
最近少し時間ができたので、落ち着いて色々なコードを見てみると、関数と感嘆符が頻繁に出てくるのを思い出します。 2 か月前に私がやったこと。ようやく杭州でのチームミーティングに参加したとき、@西子剑影が同じ質問をしました。「関数の前に感嘆符 (!) を追加するとどうなるでしょうか?」たとえば、次のコードは次のとおりです。
<span style='font-family: 微软雅黑, "Microsoft YaHei"; font-size: 14px;'>!function(){alert('iifksp')}() // true</span>
コンソールで実行した後に得られる値は true です。この無名関数は値を返さず、デフォルトの戻り値は未定義であるため、これが true である理由は簡単に理解できます。否定の結果は非常に自然です。したがって、問題は結果の値に関するものではなく、なぜ否定演算によって無名関数の自己調整が合法になるのでしょうか?
私たちは匿名関数を呼び出すためにかっこを追加することに慣れているかもしれません:
<span style='font-family: 微软雅黑, "Microsoft YaHei"; font-size: 14px;'>(function(){alert('iifksp')})() // true</span>
または:
<span style='font-family: 微软雅黑, "Microsoft YaHei"; font-size: 14px;'>(function(){alert('iifksp')}()) // true</span>
上記のかっこの位置は異なりますが、効果はまったく同じです。
では、多くの人がこの感嘆符の方法を好む理由は何でしょうか? 1 文字を保存するだけであれば、100K のライブラリでもあまりスペースを節約できない可能性があります。スペースではないため、時間の考慮事項がある可能性があることを意味します。事実は記事の最後に記載されています。
核心的な質問に戻りますが、なぜこれができるのでしょうか?さらに中心的な疑問は、なぜこれが必要なのかということです。
実際、括弧であろうと感嘆符であろうと、ステートメント全体で合法的に実行できることは 1 つだけあり、それは関数宣言ステートメントを式に変換することです。
<span style='font-family: 微软雅黑, "Microsoft YaHei"; font-size: 14px;'>function a(){alert('iifksp')} // undefined</span>
这是一个函数声明,如果在这么一个声明后直接加上括号调用,解析器自然不会理解而报错:
<span style='font-family: 微软雅黑, "Microsoft YaHei"; font-size: 14px;'>function a(){alert('iifksp')}() // SyntaxError: unexpected_token</span>
因为这样的代码混淆了函数声明和函数调用,以这种方式声明的函数 a,就应该以 a(); 的方式调用。
但是括号则不同,它将一个函数声明转化成了一个表达式,解析器不再以函数声明的方式处理函数a,而是作为一个函数表达式处理,也因此只有在程序执行到函数a时它才能被访问。
所以,任何消除函数声明和函数表达式间歧义的方法,都可以被解析器正确识别。比如:
<span style='font-family: 微软雅黑, "Microsoft YaHei"; font-size: 14px;'>var i = function(){return 10}(); // undefined 1 && function(){return true}(); // true 1, function(){alert('iifksp')}(); // undefined</span>
赋值,逻辑,甚至是逗号,各种操作符都可以告诉解析器,这个不是函数声明,它是个函数表达式。并且,对函数一元运算可以算的上是消除歧义最快的方式,感叹号只是其中之一,如果不在乎返回值,这些一元运算都是有效的:
<span style='font-family: 微软雅黑, "Microsoft YaHei"; font-size: 14px;'>!function(){alert('iifksp')}() // true+function(){alert('iifksp')}() // NaN-function(){alert('iifksp')}() // NaN~function(){alert('iifksp')}() // -1</span>
甚至下面这些关键字,都能很好的工作:
<span style='font-family: 微软雅黑, "Microsoft YaHei"; font-size: 14px;'>void function(){alert('iifksp')}() // undefined new function(){alert('iifksp')}() // Object delete function(){alert('iifksp')}() // true</span>
最后,括号做的事情也是一样的,消除歧义才是它真正的工作,而不是把函数作为一个整体,所以无论括号括在声明上还是把整个函数都括在里面,都是合法的:
<span style='font-family: 微软雅黑, "Microsoft YaHei"; font-size: 14px;'>(function(){alert('iifksp')})() // undefined(function(){alert('iifksp')}()) // undefined</span>
说了这么多,实则在说的一些都是最为基础的概念——语句,表达式,表达式语句,这些概念如同指针与指针变量一样容易产生混淆。虽然这种混淆对编程无表征影响,但却是一块绊脚石随时可能因为它而头破血流。
最后讨论下性能。我在jsperf上简单建立了一个测试:http://jsperf.com/js-funcion-expression-speed ,可以用不同浏览器访问,运行测试查看结果。我也同时将结果罗列如下表所示(由于我比较穷,测试配置有点丢人不过那也没办法:奔腾双核1.4G,2G内存,win7企业版):
オプション | コード | Ops/秒 | |||
---|---|---|---|---|---|
Chrome 13 | Firefox 6 | IE9 | Safari5 | ||
! | !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 |
新しい | 新しい関数(){;}() | 619,606 | 299,100 | 407,104 | 816,903 |
delete | delete関数(){;}() | 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 |
|| | 0 ||関数(){;}() | 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 |
さまざまな方法で生成された結果は同じではなく、違いはブラウザごとに大きく異なることがわかります。
しかし、それらの間にはまだ多くの共通点を見つけることができます。新しい方法は常に最も遅いです - そしてもちろんそれはそうです。他の多くの側面における違いは実際にはそれほど大きくありませんが、1 つ確かなことは、感嘆符は最も理想的な選択ではないということです。一方、従来の括弧はテストで常に非常に高速に実行され、ほとんどの場合、感嘆符よりも高速であるため、通常使用する方法で問題はなく、最適であるとさえ言えます。プラス記号とマイナス記号は Chrome で驚くほどパフォーマンスが良く、他のブラウザでも一般に高速で、感嘆符よりもうまく機能します。
もちろん、これは単なる簡単なテストであり、問題を説明することはできません。しかし、いくつかの結論は理にかなっています。つまり、括弧とプラス記号とマイナス記号が最適であるということです。
しかし、なぜこれほど多くの開発者が感嘆符を好むのでしょうか?これは単なる習慣の問題であり、両者の有利不利は完全に無視してよいと思います。コーディング スタイルに慣れると、この規則によりプログラムがわかりにくいものから読みやすいものに変わります。感嘆符に慣れてしまえば、括弧よりも感嘆符の方が読みやすいことは認めざるを得ません。読むときに括弧の対応を気にする必要がなく、書くときにうっかり忘れる必要がなくなります——
私も同じようにして、得意になって別の文字を保存したとき、慌てて読み出すのを忘れた 丸めたC言語の教科書の恥ずかしさと不条理… 誰でも時々忘れるものですが、再び手に取ると、手に取るものは忘れたものだけではありません。
この記事の事例を読んだ後は、この方法を習得したと思います。さらに興味深い情報については、php 中国語 Web サイトの他の関連記事に注目してください。
推奨読書:
以上がjsでの(function(){xxx})()の使い方の詳しい説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。