攻撃するJavaScript(5)の即時実行関数とクローズド


前のクローズドでは、クローズドに似た即実行関数といえば、やはり両者が混同しやすいという感じがしますが、厳密には(サイの本とハイレンジの定義が違っていますので)、即時実行関数はクローズドに該当しません.
一、丸括弧演算子
丸括弧演算子は、グループ演算子とも呼ばれます.2つの使い方があります.式を丸括弧に入れると、値を求める働きがあります.関数の後に付いている場合、機能は呼び出し関数です.
式を丸括弧に入れると、式の値が返されます.
console.log((1+2)); // 3
関数を丸括弧に入れると、関数自体が返されます.丸括弧が関数の後に続く場合は、関数を呼び出すこと、すなわち関数の値を求めることを表します.
console.log((function testa(){return 666;}));
// function testa(){return 666;}

console.log(function testa(){return 666;}());
// 666
注意:丸括弧演算子は空ではなく、エラーが発生します.
();//SyntaxError: Unexpected token )
括弧の役割は値を求めるため、文を括弧の中に入れると、エラーが発生します.
(var a = function(){return 666});
// SyntaxError: Unexpected token var
二、関数宣言functionキーを使って関数を作成し、関数名を付けて関数宣言を行います.
function testa(){}
三、匿名関数functionキーワードを使って作成された関数は、関数名が付いていませんか?匿名関数です.
function (){}
四、関数式
匿名関数を変数に割り当てますか?それは関数式です.
var testa = function (){}
実は、関数表現の根本的なところは、functionで作成された関数を関数宣言としてjsエンジンが解析するのを阻止したことです.これから詳しく話します
五、直ちに関数(IIIFE)を実行します.
すぐに関数を実行しますか?
関数をfunctionで定義した後、直ちにこの関数を呼び出します.この関数を即座実行関数と呼び、即座に呼び出される関数式IIIIFFE(Imdiately Invoked Function Expression)です.
1、本シリーズの攻撃のJavaScript(3)において、コード実行時に、先に関数宣言の関数を解析(関数宣言の向上)しますが、関数式は、プログレッシブに実行された場合にのみ解析されます.
2、関数宣言の向上により、関数宣言はすぐに実行できなくなりました.関数宣言の場合、jsは大括弧だけ解析して終了します.もし後ろに()があるなら、丸括弧演算子だけです.
function testa(){
    console.log("testa")
}("666")

//"666"
//            ,   ,     。
したがって、関数宣言の関数が発見されましたかどうかは分かりませんが、後はセミコロン(;)で区切らなくても、正常に実行できます.関数式の後にセミコロンを付けなければなりません.そうでなければ、エラーが発生します.自分で栗の検証を書いてもいいです.
3、匿名関数は単独で書くことができないので、すぐに実行できません.
function (){}
//Uncaught SyntaxError: Unexpected token (
匿名関数だけを書くと、エラーが発生します.Jsエンジンは関数宣言として解析しますが、関数宣言は関数名が必要ですので、エラーが発生します.したがって、匿名関数を使用すると、パラメータとして伝達されるか、匿名関数を関数式に変換するかがよく分かります.
4、したがって、関数式だけがすぐに実行できます.
var testa = function (){
    console.log("testa")
}()
//"testa"
上述したように、関数式とは、jsエンジンがfunctionで作成した関数124を関数宣言として解析するのを阻止したことである.
注:javascriptエンジンの規定により、もしfunctionキーワードが行頭に現れたら、すべて関数宣言文と解釈します.
したがって、解決方法としては、Fnctionを行頭に表示させないで、エンジンに式を理解させることです.
//     ,        
(function(){console.log("666")})()
(function(){console.log("666")}())

//       
!function(){console.log("666")}()
+function(){console.log("666")}()
-function(){console.log("666")}()
~function(){console.log("666")}()
関数宣言を関数表現に変換することができます.つまり、関数宣言として解析することを阻止しました.
六、即時実行関数のクローズド中のアプリケーション
1、即時実行関数は、クローズドの保存状態に対応できます.
次の前節の内容の中で閉じた例を見てみます.
function makeClosures(i){    
    var i = i;  
    return function(){
        console.log(i);     
    }
}

for (var i=1; i<=5; i++) {
    setTimeout(makeClosures(i),i*1000);  
}
//1
//2
//3
//4
//5
今すぐ実行する関数を使って簡略化します.
for (var i=1; i<=5; i++) {
    setTimeout((function(i){
        return function(){
            console.log(i);
        }
    })(i),i*1000);
}
最初の匿名関数が実行された後、2番目の匿名関数が返されます.第二の匿名関数は、setTimeoutの最初のパラメータとして入ってくる.setTimeout関数は5回実行されたので、直ちに実行関数には毎回、実行されていない匿名関数が返されます.(ここでは5つの匿名関数を返します.)匿名関数の内部には、毎回送られてくるi値が保存されています.したがって、iはそれぞれ違っています.
2、即時実行関数として、クローズドモジュール化に適用されます.
(function(){
    var meg = "hello zdx";
    
    function say(arg){
        arg = arg || meg;
        console.log(arg)
    }
    
    window.say = say;
})(window)

window.say();

//"hello zdx"
まずすぐに関数を実行します.これは匿名関数です.あなたはその関数の参照が得られないので、グローバル変数の汚染を回避します.第二に、関数の作用領域の規則のため、匿名関数の外部では関数内の変数、関数などにアクセスできない.したがって、ブロックレベルの作用領域は、直ちに関数を実行して模擬することもしばしばある.