「Webフロントエンド面接ガイド」1、JavaScriptのクローズドが浅

3800 ワード

クローズドは何ですか
クローズドは外部関数にアクセスできる内部関数の変数です.これは三つの作用領域にアクセスできます.まず、自分の役割領域(つまり、大括弧内に定義されている変数)にアクセスして、外部関数の変数にもアクセスできます.そして、大域変数にもアクセスできます.
内部関数は外部関数の変数だけでなく、外部関数のパラメータにもアクセスできます.ただし、外部関数のargmentsオブジェクトにはアクセスできません.
例をあげて説明する
JavaScriptは閉じています
function showName (firstName, lastName) {

​   var nameIntro = "Your name is ";
    //                (nameInfo)、parameter (firstName、lastName)
    ​function makeFullName () {
        
        ​return nameIntro + firstName + " " + lastName;
    
    }
​
    ​return makeFullName ();

}

​
showName ("Michael", "Jackson"); // Your name is Michael Jackson
Jqueryクローズド
$(function() {
    ​var selections = [];
    //     selections   
    $(".niners").click(function() {
        //       selections
        selections.push (this.prop("name"));
    });
});
閉塞の規則と副作用
戻るクローズドでも、外部関数の変数にアクセスできます.
JavaScriptの実行時のスコープは作成時のスコープと同じです.これは、外部関数によって返されても内部関数が外部関数の変数にアクセスできるということです.
function celebrityName (firstName) {
    var nameIntro = "This celebrity is ";
   function lastName (theLastName) {
        return nameIntro + firstName + " " + theLastName;
    }
    return lastName;
}
​
​var mjName = celebrityName ("Michael");//          celebrityName       
​
​//                   
mjName ("Jackson"); // This celebrity is Michael Jackson

クローズドが格納されているのは、外部関数の変数の参照です.
格納されているのは実際の値ではなく、クローズドが呼び出される前に、外部関数の変数の値が変化すると、より興味深いものになります.
function celebrityID () {
    var celebrityID = 999;
    //             
    return {
        getID: function ()  {
            //               celebrityID    
            return celebrityID;
        },
        setID: function (theNewID)  {
            //                   。
            celebrityID = theNewID;
        }
    }
}
​
​var mjID = celebrityID (); //   ,      celebrityID      。
mjID.getID(); // 999​
mjID.setID(567); //         celebrityID   。
mjID.getID(); // 567
閉包の副作用
開発には次のような状況があります.
​function celebrityIDCreator (theCelebrities) {
    var i;
    var uniqueID = 100;
    for (i = 0; i < theCelebrities.length; i++) {
      theCelebrities[i]["id"] = function ()  {
        return uniqueID + i;
      }
    }

    return theCelebrities;
}
​
​var actionCelebs = [{name:"Stallone", id:0},
    {name:"Cruise", id:0},
    {name:"Willis", id:0}
];
​
​var createIdForActionCelebs = celebrityIDCreator (actionCelebs);
​
​var stalloneID = createIdForActionCelebs [0];

console.log(stalloneID.id()); // 103
匿名関数を呼び出すと、uniqueIDは数字3を加えて103となり、生成されたcell ebrities IDも103であり、配列の各要素は100、101、102ではなく103である.
これは、変数の値ではなく、クローズド(すなわち、例の内部匿名関数)がアクセスする外部関数の変数の参照であるからです.このバグを解決するために、私たちは***Immedia tely Invoked Function Expression*(IIIIIIIIIIIIIIIFE)を使用してもいいです.コードは以下の通りです.
function celebrityIDCreator (theCelebrities) {
    var i;
    var uniqueID = 100;
    for (i = 0; i < theCelebrities.length; i++) {
        theCelebrities[i]["id"] = function (j)  {
            //     j          (IIFE)        i。
            return function () {
                return uniqueID + j;
                //          i  ,          。
            } () //     function      () ,       ,      uniqueID + j   ,       function。
        } (i); //        i            ,      。
    }
​
    return theCelebrities;
}
​
​var actionCelebs = [{name:"Stallone", id:0}, {name:"Cruise", id:0}, {name:"Willis", id:0}];
​
​var createIdForActionCelebs = celebrityIDCreator (actionCelebs);
​
​var stalloneID = createIdForActionCelebs [0];

console.log(stalloneID.id); // 100​​

​var cruiseID = createIdForActionCelebs [1];


console.log(cruiseID.id); // 101