ホームページ ウェブフロントエンド jsチュートリアル JavaScriptを深く理解するシリーズ(4) すぐに呼び出せる関数式_javascriptスキル

JavaScriptを深く理解するシリーズ(4) すぐに呼び出せる関数式_javascriptスキル

May 16, 2016 pm 05:57 PM

はじめに
JavaScript を学習すると、匿名関数を自己実行するコードによく遭遇します。今日は主に自己実行について説明します。
これについて詳しく知る前に、この記事でのこの機能の名前は完全に正しいとは限らないため、人によってはこれをどう理解するかによって異なります。はすぐに呼び出されるので、自分の理解に応じて名前を選択することができます。ただし、多くの人がそれを「自己実行」と呼ぶと聞きましたが、著者は後に「」と呼ぶように説得するためにこう言いました。即時呼び出し「.関数式」。
この記事の英語のオリジナルアドレス: http://benalman.com/news/2010/11/immediately-invoked-function-expression/
自己実行とは何ですか?
JavaScript では、関数に対して宣言された変数と関数は関数内にのみ存在するため、関数は実行時に実行コンテキストを作成します。このコンテキストは、関数を呼び出すときに自由変数を作成する簡単な方法を提供します。またはプライベートサブ関数。

コードをコピー コードは次のとおりです:

// この関数は別の関数を返すため、その中で、この関数は自由変数 i
// にアクセスできます。つまり、この内部関数は実際には内部オブジェクトを呼び出す権限を持っています。
function makeCounter() {
// makeCounter 内でのみアクセスできます
var i = 0;
return function () {
console.log( i); ;
}
// counter と counter2 は異なるインスタンスであり、それぞれ独自の範囲に i があることに注意してください。
var counter = makeCounter();
counter(); // ログ: 1
counter(); // ログ: 2
var counter2 = makeCounter(); ; // ログ: 1
counter2(); // ログ: 2
alert(i); // 参照エラー: i が定義されていません (i が makeCounter 内に存在するため)。


多くの場合、makeCounter の複数のインスタンスは必要ありません。場合によっては、戻り値を表示する必要もありません。

問題の核心
function foo(){} や var foo = function(){} のような関数を宣言するとき、最後に括弧を追加することで自己実行を実現できます。 foo( ) として、コードを確認します:


コードをコピーします コードは次のとおりです:
// 以下の最初の関数が必要なので、宣言された関数は、foo()、
// のように、その後に括弧 () を追加することで単独で実行できます。foo は式 function( への単なる参照であるため) ) { /* code */ }
var foo = function(){ /* code */ }
// ...最後に括弧を付けても自動的に実行できるということですか? ?
function(){ /* code */ }(); // SyntaxError: Unexpected token (
//


上記のコードは、実行してもエラーになります。パーサーがグローバル関数または関数内部関数キーワードを解析するとき、コンパイラーに明示的に指示しない場合、デフォルトで関数式ではなく関数宣言が使用され、名前のない関数がスローされるためです。関数宣言には名前が必要なため、構文エラー メッセージが表示されます。
余談: function、かっこ、syntaxError (SyntaxError)
興味深いことに、前の名前でも構文エラーが表示されますが、理由は異なります。上記では、式の後に括弧 () を追加すると、式はすぐに実行されますが、ステートメントの後に括弧 () を追加すると、意味がまったく異なり、単なるグループ化演算子

コードをコピー
コードは次のとおりです。 >// 次の関数は文法的には正しいですが、まだ単なるステートメントです // 括弧 ( )、グループ化演算子には式 function foo(){ /* code */ }(); // SyntaxError: Unexpected token ) // を含める必要があるため、引き続きエラーが報告されます。括弧 () で式を渡すと、例外はスローされません // ただし、foo 関数 function foo(){ /* code */ }( 1 );
// はまだ実行されません。これは、関数宣言の後に、無関係な関数が宣言されているコードと完全に等価です。
function foo(){ /* code */ }
( 1 );
詳細については、ECMA-262-3 の第 5 章「関数」を参照してください。
自己実行関数式
上記の問題を解決するには、JavaScript では文を括弧 () で囲むことができないため、非常に簡単です。 point function キーワードを解析するとき、パーサーは対応するコードを関数宣言ではなく関数式に解析します。
コードをコピー コードは次のとおりです:

// 次の 2 つの括弧 () はすぐに実行されます
(function () { /* code */ } ()) // これを使用することをお勧めします
(function () { /* code */ })();これも使用できます
// 括弧 () と JS の &&、XOR、カンマ、およびその他の演算子は関数式と関数宣言を明確にするため
// したがって、パーサーがそれらの 1 つがすでに式であることを認識すると、その他はデフォルトですべて式です
// ただし、次の章の内容の説明に注意してください
var i = function () { return 10; } ();
true && function (); /* code */ } ();
0, function () { /* code */ } ()
// 戻り値を気にしない場合、または難しいことを恐れない場合
// を読み取るには、単項演算記号
を追加することもできます!function () { /* code */ } ();
~function () { /* code */ } () ;
-function () { /* code */ } ();
function () { /* code */ } (); new キーワードを使用する場合もあります。も使用できますが、よくわかりません 効率
// http://twitter.com/kuvos/status/18209252090847232
new function () { /* code */ }
new function () { /* code */ } () // パラメーターを渡す必要がある場合は、括弧を追加するだけです ()

上記の括弧は、実際には曖昧さを避けるためのものです。括弧は本来関数式であることが想定されているため、まったく必要ありませんが、主に開発者が読みやすくするために、これらの自動的に実行される式を変数に割り当てるときに括弧 (() が表示されます。
クロージャを使用して状態を保存する
通常の関数を実行するときにパラメータを渡すのと同じように、自己実行します。これらのパラメータを渡されると、自己実行関数式はこれらのロックされた受信パラメータを使用して状態を効果的に保存できるため、関数式はこの方法でパラメータを渡すこともできます。

コードをコピー コードは次のとおりです:
// 変数が次のとおりであるため、このコードは間違っています。私は決してロックされていません
// 逆に、ループが実行された後は、クリックしたときにのみ値を取得します
// この時点で実際に値を取得するため
// したがって、問題はありませんどの接続がクリックされたか、最後に表示されるのは、リンク #10 です (a 要素が 10 個ある場合)
var elems = document.getElementsByTagName('a');
for (var i = 0; i <) ; elems.length; i ) {
elems[i].addEventListener('click', function (e) {
e.preventDefault();
alert('I am link #' i);
}, 'false');
}
// これは自己実行関数式クロージャ内にあるため使用できます
// i の値はロックされたインデックスとして存在し、ループ内で実行される 終了後、最終的に i の値は a 内の要素の総数 (例えば 10) になりますが
// クロージャ内の lockedIndex の値は実行されているため変化しません
// したがって、接続時間をクリックすると、正しい結果が得られます。
var elems = document.getElementsByTagName('a');
for (var i = 0; i (function (lockedIndex) {
elems[i].addEventListener('click', function (e) {
e.preventDefault();
alert('私はリンク #' lockedInIndex);
}, 'false' );
})(i);
}
// ハンドラー関数
の自己実行関数式を使用して、次のように適用することもできます。 // 外側の addEventListener の代わりに
// しかし、比較的に言うと、上記のコードの方が読みやすいです
var elems = document.getElementsByTagName('a');
for (var i = 0; i < elems .length; i ) {
elems[i].addEventListener('click', (function (lockedIndex) {
return function (e) {
e.preventDefault();
alert('私はリンク #' lockedIndex);
})(i), 'false');
実際、上記の 2 つの例の lockedIndex 変数は i に置き換えることもできます。これは外部 i と同じ関数では動作しないため、これも匿名関数クロージャの能力です。 。
自己実行匿名関数と即時実行関数式の違い
この投稿では、これを常に自己実行関数と呼んでいます。正確には、自己実行匿名関数 (Self -匿名関数の実行) ですが、元の英語のテキストでは、著者は常に即時呼び出し関数式という名前の使用を推奨してきました。著者は、説明するためにたくさんの例も示しました。
コードをコピー コードは次のとおりです:

// これは自己実行関数であり、関数自体が実行されます。内部的に、再帰的に
function foo() { foo(); }
// マークされた名前がないため、これは自己実行型の匿名関数です
// 実行するには、arguments.callee 属性を使用する必要があります
var foo = function () { argument.callee() };
// これは、foo タグ名だけがそれ自体を参照する場合もあります。 foo を別の関数に変更すると、慣れ親しんだ自己実行型の匿名関数が得られます。
var foo = function () { foo() }; これを自己実行型の匿名関数と呼ぶ人もいます。 (そうでなくても)自分自身を呼び出さないので、すぐに実行するだけです。
(function () { /* code */ } ());
// 関数式にラベル名を追加するとデバッグが容易になります
// ただし、ラベル名を付ける必要があり、関数は匿名です
(function foo() { /* code */ } ());
// 即時に呼び出される関数式 (IIFE) も自己実行できますが、一般的には使用されない可能性があります。 🎜> (function () { argument.callee(); } ());
(function foo() { foo(); } ());
// さらに、次のコードが実行されます。 BlackBerry 5 エラー、名前付き関数式で名前が定義されていないため
// はは、奇妙です
(function foo() { foo(); } ());


ここでのいくつかの例が、誰もが自己実行とは何か、即時召命とは何かを理解するのに役立つことを願っています。
注: argument.callee は ECMAScript 5 厳密モードでは廃止されているため、このモードでは使用できません。

最後のナレーション: モジュール モード
このすぐに呼び出される関数式について話しているときに、このモードに慣れていない場合は、最初にコードを見てみましょう。



コードをコピーします コードは次のとおりです: // と呼ばれる匿名関数式を作成します。すぐに
// 公開したい内容を含む変数を返します
// 返された変数は、外部で宣言された関数自体ではなく、カウンターに割り当てられます
var counter = (function () {
var i = 0;
return {
get: function () {
return i;
},
set: function (val) {
i = val ; >},
increment: function () {
return i;
}
} ()); カウンターは複数のオブジェクトです上記のコードは実際にはメソッド
counter.set(3); // 4
counter として反映します。 .increment(); // 5
counter.i; // i は返されたオブジェクトのプロパティではないため未定義です
i; // 参照エラー: i が定義されていません (i はクロージャ内にのみ存在するため)


モジュール パターンの詳細については、前回の投稿「JavaScript を深く理解するシリーズ (2): モジュール パターンの包括的な分析」を参照してください。
続きを読む
さらに詳しく知りたい場合は、上記の例のいくつかを参照して、すぐに呼び出される関数 (つまり、自己実行関数と呼ばれるもの) の式を理解していただければ幸いです。関数とモジュール パターン 詳細については、引き続き以下の Web サイトにアクセスしてください:



ECMA-262-3 の詳細第 5 章。機能
- ドミトリー A. ソシニコフ

関数と関数スコープ
- Mozilla Developer Network
    名前付き関数式
  1. - Juriy “kangax” Zaytsev モジュールモードの総合分析
  2. - Ben Cherry (翻訳・編集:おじさん) JavaScript で説明されたクロージャ
  3. - Nick Morgan
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

フロントエンドのサーマルペーパーレシートのために文字化けしたコード印刷に遭遇した場合はどうすればよいですか? フロントエンドのサーマルペーパーレシートのために文字化けしたコード印刷に遭遇した場合はどうすればよいですか? Apr 04, 2025 pm 02:42 PM

フロントエンドのサーマルペーパーチケット印刷のためのよくある質問とソリューションフロントエンド開発におけるチケット印刷は、一般的な要件です。しかし、多くの開発者が実装しています...

誰がより多くのPythonまたはJavaScriptを支払われますか? 誰がより多くのPythonまたはJavaScriptを支払われますか? Apr 04, 2025 am 12:09 AM

スキルや業界のニーズに応じて、PythonおよびJavaScript開発者には絶対的な給与はありません。 1. Pythonは、データサイエンスと機械学習でさらに支払われる場合があります。 2。JavaScriptは、フロントエンドとフルスタックの開発に大きな需要があり、その給与もかなりです。 3。影響要因には、経験、地理的位置、会社の規模、特定のスキルが含まれます。

javascriptの分解:それが何をするのか、なぜそれが重要なのか javascriptの分解:それが何をするのか、なぜそれが重要なのか Apr 09, 2025 am 12:07 AM

JavaScriptは現代のWeb開発の基礎であり、その主な機能には、イベント駆動型のプログラミング、動的コンテンツ生成、非同期プログラミングが含まれます。 1)イベント駆動型プログラミングにより、Webページはユーザー操作に応じて動的に変更できます。 2)動的コンテンツ生成により、条件に応じてページコンテンツを調整できます。 3)非同期プログラミングにより、ユーザーインターフェイスがブロックされないようにします。 JavaScriptは、Webインタラクション、シングルページアプリケーション、サーバー側の開発で広く使用されており、ユーザーエクスペリエンスとクロスプラットフォーム開発の柔軟性を大幅に改善しています。

JavaScriptを使用して、同じIDを持つArray要素を1つのオブジェクトにマージする方法は? JavaScriptを使用して、同じIDを持つArray要素を1つのオブジェクトにマージする方法は? Apr 04, 2025 pm 05:09 PM

同じIDを持つ配列要素をJavaScriptの1つのオブジェクトにマージする方法は?データを処理するとき、私たちはしばしば同じIDを持つ必要性に遭遇します...

Shiseidoの公式Webサイトのように、視差スクロールと要素のアニメーション効果を実現する方法は?
または:
Shiseidoの公式Webサイトのようにスクロールするページを伴うアニメーション効果をどのように実現できますか? Shiseidoの公式Webサイトのように、視差スクロールと要素のアニメーション効果を実現する方法は? または: Shiseidoの公式Webサイトのようにスクロールするページを伴うアニメーション効果をどのように実現できますか? Apr 04, 2025 pm 05:36 PM

この記事の視差スクロールと要素のアニメーション効果の実現に関する議論では、Shiseidoの公式ウェブサイト(https://www.shisido.co.co.jp/sb/wonderland/)と同様の達成方法について説明します。

Console.log出力の違い結果:なぜ2つの呼び出しが異なるのですか? Console.log出力の違い結果:なぜ2つの呼び出しが異なるのですか? Apr 04, 2025 pm 05:12 PM

Console.log出力の違いの根本原因に関する詳細な議論。この記事では、Console.log関数の出力結果の違いをコードの一部で分析し、その背後にある理由を説明します。 �...

JavaScriptは学ぶのが難しいですか? JavaScriptは学ぶのが難しいですか? Apr 03, 2025 am 12:20 AM

JavaScriptを学ぶことは難しくありませんが、挑戦的です。 1)変数、データ型、関数などの基本概念を理解します。2)非同期プログラミングをマスターし、イベントループを通じて実装します。 3)DOM操作を使用し、非同期リクエストを処理することを約束します。 4)一般的な間違いを避け、デバッグテクニックを使用します。 5)パフォーマンスを最適化し、ベストプラクティスに従ってください。

フロントエンド開発でVSCodeと同様に、パネルドラッグアンドドロップ調整機能を実装する方法は? フロントエンド開発でVSCodeと同様に、パネルドラッグアンドドロップ調整機能を実装する方法は? Apr 04, 2025 pm 02:06 PM

フロントエンドのVSCodeと同様に、パネルドラッグアンドドロップ調整機能の実装を調べます。フロントエンド開発では、VSCODEと同様のVSCODEを実装する方法...

See all articles