ホームページ > ウェブフロントエンド > jsチュートリアル > Javascript の匿名関数と自己実行関数の簡単な分析_JavaScript スキル

Javascript の匿名関数と自己実行関数の簡単な分析_JavaScript スキル

WBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWB
リリース: 2016-05-16 15:16:00
オリジナル
1200 人が閲覧しました

関数は JavaScript で最も柔軟なオブジェクトです。ここではその匿名関数の使用法のみを説明します。無名関数:関数名のない関数です。

関数の定義は大きく分けて次の 3 つの方法があります。

最初のタイプ: これも最も一般的なタイプです

1

2

3

function double(x){

return 2 * x;

}

ログイン後にコピー

2 番目の方法: このメソッドは Function コンストラクターを使用し、パラメーター リストと関数本体の両方を文字列として扱います。これは非常に不便なので、お勧めできません。

1

var double = new Function('x', 'return 2 * x;');

ログイン後にコピー

3 番目のタイプ:

1

var double = function(x) { return 2* x; }

ログイン後にコピー

「=」の右側の関数は無名関数であることに注意してください。関数を作成した後、関数は変数 square に代入されます。

匿名関数の作成

最初の方法は、上で述べたように二乗関数を定義することであり、これも最も一般的に使用される方法の 1 つです。

2 番目の方法:

1

2

3

(function(x, y){

alert(x + y);

})(2, 3);

ログイン後にコピー

ここ (最初の括弧内) で匿名関数が作成され、2 番目の括弧を使用して匿名関数を呼び出し、パラメーターを渡します。括弧は式であり、式には戻り値があるため、括弧の後に

を追加できます。

自己実行匿名関数

1. 自己実行匿名関数とは何ですか?

これは次のような関数を指します: (function {// code})();

2. 質問

(function {// code})(); は実行できるのに、function {// code}(); がエラーを報告するのはなぜですか?

3. 分析

(1) まず、この 2 つの違いを理解する必要があります。
(function {// code}) は式、function {// code} は関数宣言です。
(2) 次に、js の「プリコンパイル」の特徴:
js の「プリコンパイル」フェーズでは、関数宣言は解釈されますが、式は無視されます。
(3). js が function() {//code}(); を実行するとき、function() {//code} は「プリコンパイル」段階で解釈されているため、js は function(){/ /code} をスキップします。 (); を実行しようとしているため、エラーが報告されます
jsが(function {// code})();を実行すると、(function {// code})は式なので、戻り値が関数なので、jsはそれを解いて戻り値を取得します。 ;、実行されます。

さらに、関数を式に変換する方法は、必ずしもグループ化演算子 () に依存するわけではありません。void 演算子、~ 演算子、! 演算子も使用できます。

例:

1

2

3

!function(){

alert("另类的匿名函数自执行");

}();

ログイン後にコピー

匿名関数とクロージャ

クロージャを意味する英語はクロージャです。クロージャは JavaScript の知識の非常に重要な部分です。クロージャを使用すると、コードの量が大幅に削減され、コードがより明確に見えるなどの効果があるためです。つまり、クロージャは非常に強力です。

クロージャの意味: 端的に言えば、クロージャは関数の入れ子です。たとえ外側の関数が実行されていても、内側の関数は外側の関数のすべての変数を使用できます (これには JavaScript スコープ チェーンが関係します)。

1

2

3

4

5

6

7

function checkClosure(){

var str = 'rain-man';

setTimeout(

function(){ alert(str); } //这是一个匿名函数

, 2000);

}

checkClosure();

ログイン後にコピー

この例は非常に単純に見えますが、実行プロセスを注意深く分析すると、まだ多くの知識ポイントがあります。checkClosure 関数の実行は瞬時に行われ (おそらく 0.00001 ミリ秒しかかかりません)、変数 str が関数本体に作成されます。 setTimeout の匿名関数が str への参照を持っているため、 checkClosure の実行後に str は解放されません。 2 秒後、関数本体内の匿名関数が実行され、str が解放されます。

クロージャを使用してコードを最適化する:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

function forTimeout(x, y){

alert(x + y);

}

function delay(x , y , time){

setTimeout('forTimeout(' + x + ',' + y + ')' , time);

}

/**

* 上面的delay函数十分难以阅读,也不容易编写,但如果使用闭包就可以让代码更加清晰

* function delay(x , y , time){

* setTimeout(

* function(){

* forTimeout(x , y)

* }

* , time);

* }

*/

ログイン後にコピー

匿名関数の最大の用途は、クロージャ (JavaScript 言語の機能の 1 つ) を作成することです。また、名前空間を構築してグローバル変数の使用を減らすこともできます。

1

2

3

4

5

6

7

8

var oEvent = {};

(function(){

var addEvent = function(){ /*代码的实现省略了*/ };

function removeEvent(){}

 

oEvent.addEvent = addEvent;

oEvent.removeEvent = removeEvent;

})();

ログイン後にコピー

このコードでは、addEvent 関数とremoveEvent 関数はローカル変数ですが、グローバル変数 oEvent を通じてそれを使用できます。これにより、グローバル変数の使用が大幅に削減され、Web ページのセキュリティが強化されます。

次のコードを使用します:

1

2

3

4

5

6

7

8

9

oEvent.addEvent(document.getElementById('box') , 'click' , function(){});

var rainman = (function(x , y){

return x + y;

})(2 , 3);

/**

* 也可以写成下面的形式,因为第一个括号只是帮助我们阅读,但是不推荐使用下面这种书写格式。

* var rainman = function(x , y){

* return x + y;

* }(2 , 3);

ログイン後にコピー

ここでは変数 Rainman を作成し、匿名関数を直接呼び出すことでそれを 5 に初期化します。この小さなトリックは場合によっては非常に実用的です。

1

2

3

4

5

6

7

8

9

10

11

12

var outer = null;

(function(){

var one = 1;

function inner (){

one += 1;

alert(one);

}

outer = inner;

})();

outer(); //2

outer(); //3

outer(); //4

ログイン後にコピー

このコードの変数 1 はローカル変数 (関数内で定義されているため) であるため、外部からアクセスできません。ただし、ここでは変数 one にアクセスできる inner 関数を作成し、グローバル変数 external は inner を参照するため、outer を 3 回呼び出すと増分結果がポップアップされます。

注意

1 クロージャにより、内部関数は親関数内の変数を参照できますが、変数は最終値です

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

/**

* <body>

* <ul>

* <li>one</li>

* <li>two</li>

* <li>three</li>

* <li>one</li>

* </ul>

*/

var lists = document.getElementsByTagName('li');

for(var i = 0 , len = lists.length ; i < len ; i++){

lists[ i ].onmouseover = function(){

alert(i);

};

}

ログイン後にコピー

你会发现当鼠标移过每一个

  • 元素时,总是弹出4,而不是我们期待的元素下标。这是为什么呢?注意事项里已经讲了(最终值)。显然这种解释过于简单,当mouseover事件调用监听函数时,首先在匿名函数( function(){ alert(i); })内部查找是否定义了 i,结果是没有定义;因此它会向上查找,查找结果是已经定义了,并且i的值是4(循环后的i值);所以,最终每次弹出的都是4。

    解决方法一:

    1

    2

    3

    4

    5

    6

    7

    8

    var lists = document.getElementsByTagName('li');

    for(var i = 0 , len = lists.length ; i < len ; i++){

    (function(index){

    lists[ index ].onmouseover = function(){

    alert(index);

    };

    })(i);

    }

    ログイン後にコピー

    解决方法二:

    1

    2

    3

    4

    5

    6

    7

    var lists = document.getElementsByTagName('li');

    for(var i = 0, len = lists.length; i < len; i++){

    lists[ i ].$$index = i; //通过在Dom元素上绑定$$index属性记录下标

    lists[ i ].onmouseover = function(){

    alert(this.$$index);

    };

    }

    ログイン後にコピー

    解决方法三:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    function eventListener(list, index){

    list.onmouseover = function(){

    alert(index);

    };

    }

    var lists = document.getElementsByTagName('li');

    for(var i = 0 , len = lists.length ; i < len ; i++){

    eventListener(lists[ i ] , i);

    }

    ログイン後にコピー

    2 内存泄露

    使用闭包十分容易造成浏览器的内存泄露,严重情况下会是浏览器挂死

  • このウェブサイトの声明
    この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
    人気のチュートリアル
    詳細>
    関連するチュートリアル
    人気のおすすめ
    最新のコース
    最新のダウンロード
    詳細>
    ウェブエフェクト
    公式サイト
    サイト素材
    フロントエンドテンプレート