javascriptいくつかの知識点

14505 ワード

この文章はjavascriptのいくつかの比較的に重要な知識点をまとめます.scope chain、this、関数のいくつかの高級な特性を含みます.モーニング娘
scope chain
scope chainはjavascript関数呼び出しの中で最も核心的な概念で、特に閉塞の概念を理解するには、まずscope chainの原理を理解しなければなりません.
関数はscope chain上で変数を検索します.
functionを実行すると、scope chainが一番下から上に変数を検索します.scope chainの最初のオブジェクトは自分の呼び出しオブジェクト、次いで外側の層のfunctionの呼び出しオブジェクト、そしてより外側の層の呼び出しオブジェクト、global ojectまでです.
このコードのように:
function wrapper(){

    var name = "kyfxbl";

    function inner(){
        console.log(name);
    }

    inner();
}
inner実行時には、自分の呼び出し先に変数nameがないので、wrapperの呼び出し先を検索します.もしwrapperの呼び出し対象がなかったら、グローバル変数の中に探しに行きます.
scope chainは関数定義時に決定します.
javascriptのスコープ規則は語法のスコープです.つまり、関数のscope chainは定義時に決められます.呼び出し時に決められたのではありません.
例えばこのコード:
function wrapper(){

    var scope = "local";

    return function(){
        console.log(scope);
    }

}

var f = wrapper();

var scope = "global";

f();
戻ってきた匿名関数は、その役割領域がwrapper()の実行時に確定されました.f()を実行するときに決めるのではなく
scope chain上の呼び出しオブジェクトは変更できます.
一つの関数は定義された時、scope chainはもう確定しましたが、scope chainにはどのオブジェクトが含まれているかを確定しました.これらのオブジェクトの属性は、このコードのように変更できます.
function wrapper(){

    var name = "original";

    function setName(new_name){
        name = new_name;
    }

    function getName(){
        console.log(name);
    }

    return [setName, getName];
}

var funcs = wrapper();

funcs[1]();// original
funcs[0]("new_name");
funcs[1]();// new_name
wrapper()が呼び出された時、2つの関数が定義されました.この2つの関数のscope chainでは、wrapperのcall objectを共有しています.だからsetNameを呼び出すとnameの値が変わり、getName()にも影響が出ます.scope chainは確定していますが、オブジェクトの属性は変更できます.
クローズドはどのように形成されますか?
簡単に言えば、ネスト関数が戻り値として外部の変数によって参照されたり、外部のオブジェクトの属性として閉じられたりすると、このようになります.クローズドになったら、scope chain上の呼び出し対象は、すぐにゴミに回収されずにそのまま使えます.サイの本にはもっと詳しい説明があります.
a function is executed in the scope in which it was defined.When a function is invoked,a call oject is created for it and plocd on the scope chain.When the function exits,the cal obiject is removed from the opnese.Onese.the scope chain is the only reference to the cal object.When the object is removed from the chain,there re no more references to it,and it ends up being garbage colleced.Butnese ted functions changethe definition of that function refers to the cal oject s because that cal object is the top of the scope chain the function was defined.If the nect function is used within the Fter function,hover the funce the the funcethe nese ted function refers to the call object,and the cal object refers to ness ted function,but there reのother references to eigther one,and so both object s becomme available for garbage collection.Things are different if You save a reference to the ness ted function in the global scope.You do so by the nese function the the return funce thethere is an external reference to the ness ted function,and the ness ted function retains its reference to the call oject of the outer function.The up shot is the cant offect for that one partical invo of the Outer functions,The Live.and the names and values of the function argments and local variables persist in this oject.JavaScript code cannot directly the canc oject in way,but the properties defines are parte of the funce
すべての変数は、オブジェクトの属性です.
  • は、functionの内部で、varによって宣言される変数であり、一時変数であり、実質的に呼び出し対象の属性
  • である.
  • は、function内で、functionで宣言する関数であり、一時変数
  • である.
  • は、function内部で、varによって宣言された変数ではなく、グローバル変数であり、本質的にはグローバルオブジェクトの属性である.strickモードを使用すると、このような書き方は禁止されています.
  • は、任意のfunction内ではなく、宣言された変数であり、グローバル変数
  • である.
    以下のコードの例を説明します.
    (function(){
    
        var a = function(){
            console.log("a");
        };
    
        b = function(){
            console.log("b");
        };
    
        function c(){
            console.log("c");
        }
    
    })();
    
    a();// error
    b();// ok
    c();// error
    nodeとブラウザの環境は、表現に少し違いがあります.ブラウザ環境では、Function外部宣言の変数は、グローバルオブジェクトwindowの属性です.nodeの環境で、直接globalの属性になることはできなくて、実はnodeのすべてのファイルがひとつの匿名のfunctionに包まれているためです.
    どのオブジェクトを指しますか?
    javascriptとjavaの中のthisは、全く違います.javaにおけるthisの意味は非常に明確であり、すなわち現在の例である.javascriptの中のthisはずっと複雑です.たとえば以下のコード:
    function doSomething(){
        console.log(this.name);
    }
    このコードだけを見ていると、運転中にどのオブジェクトを指すのか確認できません.javascriptの中のthisがどのオブジェクトを指すかを決定するには、コンテキストに依存しなければなりません.全部で5つの状況があります.
    オブジェクトとしてのメソッドが呼び出されます.
    var obj = {
        name: "kyfxbl"
    };
    
    obj.sayHi = function(){
        console.log(this.name);
    };
    
    obj.sayHi();
    functionがある対象となる方法で呼び出された場合、thisはその対象を指します.
    直接呼び出し
    global.name = "kyfxbl";
    
    function sayHi(){
        console.log(this.name);
    }
    
    sayHi();
    global.name = "kyfxbl";
    
    function wrapper(){
    
        (function(){
            console.log(this.name);
        })();
    }
    
    wrapper();
    直接呼び出し時、thisはグローバルオブジェクトを指し、ブラウザ環境ではwindow、node環境はglobalです.
    コンストラクタとして呼び出される
    function Person(name){
        this.name = name;
    }
    
    var person = new Person("kyfxbl");
    
    console.log(person.name);
    functionがコンストラクターとして呼び出されると、新たに作成されたそのオブジェクトにthisが向けられます.OOプログラミングでは、これは一般的な形式です.
    コールとアプリで呼び出す
    function sayHi(){
        console.log(this.name);
    }
    
    var obj = {
        name: "kyfxbl"
    };
    
    sayHi.call(obj);
    この場合、thisはcallの最初のパラメータです.
    トップコードでの挙動
    トップレベルの環境では、すなわち任意のfunction内部にないthisは、ブラウザ環境とnode環境では異なります.
    node環境では、以下のコードの出力結果が予想外かもしれません.
    console.log(this === exports);// true
    console.log(this === global);// false
    
    (function(){
        console.log(this === exports);// false
        console.log(this === global);// true
    })();
    トップレベルの環境では、globalではなく、module.exportsを指します.
    ブラウザ環境では、最上階のthisがwindowを指します.
    alert(this === window);// true
    これはブラウザの環境とnode環境の違いです.
    functionの高級属性
    フュージョンには高級な属性がありますので、普段はあまり使わないかもしれませんが、フレームやライブラリを書く時には必ず使わなければなりません.
    appyとcall関数
    applyとcallにより、関数の動的呼び出しが可能です.
    この2つの関数は非常に近いです.唯一の違いは、appyはパラメータ配列を伝えることです.
    argmentsとthis
    関数が呼び出されると、自動的にargmentsオブジェクトが作成されます.配列と同じ挙動ですが、配列ではありません.argmentsでパラメータの状況を動的に判断できます.
    もう一つのキーワードはthisです.前に紹介しました.
    各functionの内部にはこの2つのキーワードがありますので、関数がネストされている場合、内部関数のthisとargmentsは外層関数のthisとargmentsをカバーします.したがって、内部関数内の外層関数にアクセスする必要がある場合、この2つの属性は、通常は次のようになります.
    function wrapper(age){
    
        var that = this;
    
        var thatArguments = arguments;
    
        function inner(){
            console.log(that.name);
            console.log(thatArguments);
        }
    
        inner();
    }
    
    var obj = {
        name: "kyfxbl"
    };
    
    wrapper.call(obj, 23);// kyfxbl, {'0': 23}
    length属性
    lengthは、このfunctionの変形の個数を表しています.
    function sayHi(name, words){
        // logic
    }
    
    console.log(sayHi.length);// 2
    caler
    calerは、現在この関数を呼び出している外層関数を指し、自身が最外層の関数である場合、nullに戻ります.
    function wrapper(){
    
        function inner(){
            console.log(inner.caller.toString());
        }
    
        inner();
    }
    
    wrapper();
    また、node環境では、最外層のfunctionは、そのcalerがnullではなく、ある関数です.これもnodeの中のすべてのファイルを説明していますが、実は一つのfunctionに包まれています.
    function test(){ console.log(test.caller.toString()); } test();
    出力は:
    function (exports, require, module, __filename, __dirname) { 
    
        function test(){
            console.log(test.caller.toString());
        }
    
        test();
    }
    calee
    caleeはargmentsの属性の一つで、自分を指す.function自身の参照を取得する必要がある場合は、この属性を使用します.例えば匿名関数の再帰的呼び出しを実現する.
    function test(){
        console.log(arguments.callee === test);
    }
    
    test();// true
    "script type="text/javascript""('').('pre.prettyprint code').each(function(){var lins=$(this).text().split(').length;var$numberging=('ul/ad' dededededededededededededededededededededededededededededededededededededen.(())).clininininininininininininininindedededededededededededededededededededededededededededededededededededededededededede. apped($numberging);for(i=1;i<=lineas;i+){$numberging.appnd('
  • ').text(i)};;$numberging.fadeIn(1700);)