『JavaScriptモード』読書ノート(4)—関数4

14101 ワード

この記事は主にリアルタイムオブジェクトの初期化、初期化時の分岐、関数の属性-スペアモード、およびオブジェクトの設定を学びます.この編の内容はちょっと多いです.
 
六、インスタントオブジェクト初期化
グローバルスコープを汚染されないように保護する別の方法、インスタントオブジェクト初期化モード.このモードは、オブジェクトを作成した直後に実行するinit()メソッドを有するオブジェクトを使用する.init()関数はすべての初期化タスクを担当する必要があります.
({
    //           
    //       
    maxwidth:600,
    maxheight:400,

    //             
    gimmeMax:function () {
        return this.maxwidth + "x" + this.maxheight;
    },
    
    //    
    init:function() {
        console.log(this.gimmeMax());
        //        
    }
}).init()
文法的には、このようなパターンは対象の字面量を使って普通のオブジェクトを作成するようです.文字どおりの量を括弧に包装してもいいです.JavaScriptエンジンは、コードブロックとしてではなく、大括弧を対象の字面量としています.この括弧が終わったら、すぐにinit()メソッドを呼び出すことができます.
この2つの方法はすべて実行できます.
({...}).init();
({...}.init());
この方法は、一括初期化タスクを実行する際に、グローバル名前空間を保護することができる.
このようなモードは、コードの山を匿名関数にパッケージするだけの方法と比較して、より多くの文法的特徴に関連するように見えるが、初期化タスクがより複雑であれば、初期化プロセス全体がより構造的に見える.例えば、プライベートヘルプ関数は、彼らが一時的なオブジェクトの属性であることを明らかにしています.また、インスタント関数モードでは、彼らは単に各所に分散している関数である可能性が高いです.
このモードは主に1回限りのタスクに適用され、init()が終了してもそのオブジェクトに対するアクセスがなく、init()が終了したらそのオブジェクトに対する1つの参照を保存したいなら、init()の末尾に「return this」という語句を付加することで実現することができます.
var a = ({
    //           
    //       
    maxwidth:600,
    maxheight:400,

    //             
    gimmeMax:function () {
        return this.maxwidth + "x" + this.maxheight;
    },
    
    //    
    init:function() {
        console.log(this.gimmeMax());
        //        
        return this;
    }
}).init()
console.log(a.maxheight)
 
七、初期化時分岐
初期化時分岐(Init-time brancing)は最適化モードです.ある条件がプログラムの宣言期間中に変更されないことがわかった時、その条件に対して一回だけテストした時には意味があります.ブラウザで嗅ぎ付けるのは典型的な例です.
DOM要素の計算パターンまたは付加的なイベントハンドラを特定することは、初期化時のブランチモードから恩恵を受けることができるもう一つのシーンである.ほとんどのプログラム開発者はこのようなコードを作成しました.少なくとも一回は彼らのクライアントプログラムライフサイクル内で、イベントモニターを追加または削除するためのツールとしても使えます.
//   
var utils = {
    addListener: function(el,type,fn) {
        if(typeof window.addEventListener === 'function') {
            el.addEventListener(type,fn,false);
        } else if(typeof document.attachEvent === 'function') { //'IE'
            el.attachEvent('on' + type,fn);
        } else {
            el['on' + type] = fn;
        }
    },
    removeListener:function(el,type,fn){
        //     
    }
}
この部分はコードの効率が悪いです.utils.addListener()またはutils.removeListener()を呼び出すたびに、同じ検査が繰り返されます.
初期化されたブランチを使用すると、スクリプト初期化ローディング時にブラウザの特徴を一度に検出することができる.この場合、全ページライフサイクルで関数の運転方式を再定義できます.
//   
var utils = {
    addListener:null,
    removeListener:null
};
//  
if(typeof window.addEventListener === 'function') {
    utils.addListener = function(el,type,fn){
        el.addEventListener(type,fn,false);
    };
    utils.removeListener = function(el,type,fn){
        el.removeEventListener(type,fn,false);
    };
} else if(typeof document.attachEvent === 'function') { //   IE   
    utils.addListener = function(el,type,fn){
        el.attachEvent('on' + type,fn);
    };
    utils.removeListener = function(el,type,fn){
        el.detachEvent('on' + type,fn);
    };
} else { //     
    utils.addListener = function(el,type,fn){
        el['on' + type] = fn;
    };
    utils.removeListener = function(el,type,fn){
        el['on' + type] = null;
    };
}
実は、簡単に言えば、ブランチ初期化の意味は、重複したことを一回だけすることです.
 
八、関数の属性—ディップモード
関数はオブジェクトですので、属性があります.実際には、属性と方法があります.例えば、各関数に対して、どのような文法を使って作成しても、自動的にlength属性が得られます.この関数が期待するパラメータの数が含まれています.
function func(a, b, c) {}
console.log(func.length); //3
いつでもユーザー定義の属性を関数に追加できます.カスタム属性の1つの用例は、キャッシュ関数の結果(すなわち、戻り値)であるため、次の関数の呼び出し時に、潜在的な重い計算をやり直す必要はない.キャッシュ関数の結果は、メモとも呼ばれます.
var myFunc = function (param) {
    if(!myFunc.cache[param]) {
        var result = {};
        // ...         ...
        myFunc.cache[param] = result;
    }
    return myFunc.cache[param];
};

//     
myFunc.cache = {};
上記の例では、関数myFunは、myFun.cacheを介して通常のようにアクセスできる属性cacheを作成した.cache属性は、キーとして関数に渡すパラメータparamを使用して、計算結果を値とします.計算結果は必要な任意の複雑なデータ構造であってもよい.
上のコードは、この関数はパラメータparamだけが必要であり、基本的なデータタイプであると仮定しています.より多くのより複雑なパラメータがあるならば、これに対する一般的な解決策はそれらを逐次化することである.すなわち、パラメータオブジェクトをJSON文字列に順番に並べて、cacheオブジェクトのキーとしてこの文字列を使用することができる.
var myFunc = function () {
    var cachekey = JSON.stringify(Array.prototype.slice.call(arguments)),
        result;
    if(!myFunc.cache[cachekey]) {
        result = {};
        // ...         ...
        myFunc.cache[cachekey] = result;
    }
    return myFunc.cache[cachekey];
};

//     
myFunc.cache = {};
プログレッシブ化の過程で、オブジェクトの「表示」が失われることに注意してください.2つの異なるオブジェクトがあり、ちょうど同じ属性を持つ場合、この2つのオブジェクトは同じキャッシュエントリを共有します.
前の関数を編纂する別の方法は、ハードコード関数名を使用するのではなく、argments.caleeを使用して関数を参照することである.現在は可能ですが、ES 5の厳格なモードではargments.caleeはサポートされていません.
var myFunc = function (param) {
    var f = arguments.callee,
        result;
    if(!f.cache[param]) {
        result = {};
        // ...         ...
        f.cache[param] = result;
    }
    return f.cache[param];
};

//     
myFunc.cache = {};
 
九、オブジェクトの設定
設定対象パターンは、より簡潔なAPIを提供する方法であり、特にライブラリを作成する場合、または他のプログラムによって使用されるコードのいずれかを提供する場合である.
実は配置対象の概念は簡単です.おそらくすでに開発作業に使われています.
//              ,         。
//   ,        addPerson()   ,               。
function addPerson(first,last){
    //...
};

//   ,         ,  ,    ,         
//             
function addPerson(first,last,gender,address,phone){
    //...
};

//   ,        ,      ,     。
//
function addPerson(first,last,gender,address,phone,username,addDate){
    //...
};

//    ,     ,       
addPerson('first','last','gender',null,null,'username','addDate');

//
したがって、一つのパラメータだけを使って、すべてのパラメータを表してもいいです.このパラメータのオブジェクトをconf、すなわち「構成」の意味にします.
addPerson(conf);
そして、この関数の使用者は、このようにしてもよい.
var conf = {
    username:'zaking',
    first:"Bruce",
    last:"Wayne"
};
addPerson(conf);
オブジェクトを設定するメリットは、
  • は、多くのパラメータおよびその順序を記憶する必要がない.
  • は、任意のパラメータを安全に無視することができる.
  • は、より読みやすく、維持しやすい.
  • は、パラメータの追加と削除をより容易にする.
  • 短所はこうです.
  • はパラメータ名を記憶する必要があります.
  • 属性名は圧縮できません.
  • 関数がDOM要素を作成する場合、このようなモードは、要素およびスタイルが多くのオプション的な特徴および属性を有することがあるので、例えば、設定要素のCSSスタイルにおいて使用することができる.
     
    この文章の内容はここまでです.全部小さいpointですが、実際に勉強する必要があります.次の章は関数部分の最後の章になります.私たちは「Curry化」について話します.