学学学AOPの装飾者モード


装飾者、英語名decorator.「装飾」というのは、文字通り簡単に理解できますが、土肥を丸くしたり、化粧をしたりして、華やかに白富美に振り向いたりしますが、本体は土肥円です.
人の話をする咳~
jsではすべてオブジェクトであり,関数は一等オブジェクトである.通常のObjectでは,属性や他の方法を容易に追加することができ,もちろん関数も例外ではない.しかし、このような結果は、鳳姐を整形手術に送るように、本体を絶えず変えることです.もちろん、結果は良いか悪いか、鳳姐は次のangelababyかもしれない.だから、私たちのコードの純潔度(たとえあなたが醜いアヒルであっても)のために、私たちはナイフを動かさずに、あなたを白くて美しいものにすることができます.

リファレンス装飾


これは装飾の初級段階で、粉を塗るだけです.jsでは、リファレンス装飾と呼ばれています.
talk is cheap, show u code
//   jimmy           
var jimmy = function(){
    console.log("jimmy");
}
var _jimmy = jimmy;
jimmy = function(){
    _jimmy();
    console.log("I love HuaHua");
}
jimmy();

この応用シーンは主にマルチコラボレーションとフレームワーク設計にある.例えば、李氷岩はすでにonload関数を使っていますが、小舟はまたonload関数を使いたいと思っています.これは問題になります.もし小舟が直接変更すれば、彼は李氷岩が書いた蜜汁コードを見なければなりません.そして、間違いを起こさないようにしなければなりません.これは間違いなく難しいので、ここでは引用装飾を使ってonloadに層を追加することができます.
//         
var xiaoLi = function(){
    console.log("    ");
}
window.onload = xiaoLi;  //       onload   
//         onload  
var fn = window.onload;
var xiaoZhou = function(){
    fn();
    conosle.log("    ");
}
window.onload = function(){  //  onload   ,        code
    xiaoZhou();
}

だから引用装飾の使い道は大きい.上你妹啊~~啊...(もう一つのMe)上の引用パターンにどのような弊害があるかを分析してみましょう(利点はすでに知っています).まず、参照モードを使用する場合、上記の「fn」のような余分な参照オブジェクトが必ず追加される.また、プログラムチェーンが増加するにつれて、中間オブジェクトは必ずノードと同じ数になります.もちろん、名前をつけては言いません.肝心なのは、無駄なコードがたくさん置いてあるので、気分が悪いことです.そこで、ここではAOPのデコレーションモードを導入する.

AOPデコレーション


親切、熟知、完璧.AOPは一度だけではないはずです.在職責任チェーンモードで使用したことがあります.反復器モードで使用したことがあります.こんなに何度も使っているのに、AOPについて基本的な説明はまだしていないようですね?だから、ここでみんなにシュウシュウをあげます.AOPの中国語名は切面向けプログラミングです.まずこの名詞を言いますと、「向き」という言葉は説明しなくてもいいはずですが、肝心な「うどん」は何ですか.もし皆さんがsangwichを作ったことがあれば、まずパンを買ってきて、パンを切って、それからうどんの上にflavoringを加えなければなりません.例えば、野菜、ハム、ベーコンなどです.はい、jsプログラムと比較すると、1つのプログラムチェーンはあなたが買ったパンに相当します.flavoringはあなたが追加したい機能関数で、どのように関数をプログラムチェーンの中で適切な位置に正確に置くか、これはAOPがしたことです.まず、2つの動的関数をもう一度シュウシュウします.
Function.prototype.after = function(fn){
    var _this = this;
    return function(){
        var res = _this.apply(this,arguments);
        fn.apply(this,arguments);
        return res;
    }
}
Function.prototype.before = function(fn){
    var _this = this;
    return function(){
        fn.apply(this,arguments);  
        return    _this.apply(this,arguments);
    }
}

この二つの関数の組み合わせはjs中のAOPモードの精華を構成した.AOPで最もよく使われるのは、ビジネスロジックに関係のない機能がメインプログラムに動的に織り込まれていることです.
talk is cheap , show u code
栗を挙げましょう:AOPコンピューティングプログラムを使用してイベントを実行します
//           
function factorial(n) {  //        
  if (n === 1) return 1;
  return n * factorial(n - 1);
}
function calTime(n){
    var start = new Date().getMilliseconds();
    factorial(n);
    console.log(new Date().getMilliseconds() - start+"ms");
}
calTime(1000);

時間がかかることができますが、他の関数がテストする必要がある場合は、このような意味はあまり価値がありません.AOPを用いて再構成を行った.
function factorial(n) {  //        
  if (n === 1) return 1;
  return n * factorial(n - 1);
}
var calTime = (function(){
    var start;
    return    function(){
        if(!start){  //       
            start = new Date().getMilliseconds();
        }else{
            console.log(new Date().getMilliseconds()-start+"ms");
            start = undefined;
        }
    }
})();
var calcu = factorial.before(calTime).after(calTime)(200);

これでいいタイミング機能をビジネスロジックから抽出して、本当にangelababyの味がしますね.AOPを使用する場合は、before&afterの実行が完了すると、返される結果が最初の関数の内容になることに注意してください.
var result = function(){
    return 1;
}.before(function(){
    return 2;
}).after(function(){
    return 3;
});
console.log(result());  //1

AOPの用法と理論を大まかに理解し、冒頭に述べた例に対して再構成することができる.
window.onload = function(){
    console.log("       ");
}
var fn = window.onload;
fn.before(function(){
    console.log("    ");
});
window.onload = fn;

上の栗よりずっとはっきりしていて、beforeやafterを使うのもコードの読みやすいように見えます.

AOPデコレーションの例


上の例では、AOP装飾モードの目立たないコーナーとしか言えません.AOPが引用したシーンはjs中、あるいはどの言語でも大活躍している.jsでは「細粒度」オブジェクトがプログラムで最も多重性の高いオブジェクトであり,オブジェクトを細粒度で表すことができるので,AOPは間違いなく最適な選択である.ビジネスロジックを書くとき、私たちの最大の問題はロジックを判断し、if文を大量に使用することです.これは思考を経て巧みに解消することができます.例えば、私は購入コースを書くときにいくつかの論理に遭遇します.カリキュラム数が要求に合致する場合にのみ、購入の効果が有効である.通常のビジネスロジックで作成
var buy = function(){
    if(confirm()){  //          
        http.buyCourse('xxx');  //    
    }
}
var confirm = function(){
    console.log("      ");
}
document.querySelector(".buy").addEventListener("click",function(){
    buy();
},false);

AOPデコレーションモードで再構築後
var buy = function(){
    http.buyCourse("xxx"); //       ,  
}
var confirm = function(){
    console.log("      ");
}
var buy = buy.before(confirm);
document.querySelector(".buy").addEventListener("click",function(){
    buy();
},false);

美美コードたっぷりの即视感!!!いいえ、ボス、栗の砂糖炒めをもう一つください.いいですよ.ここでは関数の結果を得ただけです.伝達パラメータに直接介入したいのですが、よろしいでしょうか.もちろんいいです.beforeの内部構造を検討します(afterは同じです)
Function.prototype.before = function(fn){
    var _this = this;
    return function(){
        fn.apply(this,arguments);  
        return    _this.apply(this,arguments);
    }
}

ここでargumentsは参照タイプであるため、fnがargumentsを変更すると_に反映されるthis.applyのargumentsも変わります.このアプリケーションシーンはajaxのアドレスに必要なパラメータを追加することです.実際のプロジェクトでは、最初のインタフェースは、一般的なアドレスであり、リクエストを送信し、パラメータを取得します.
http.ajax(url,type).then(...)

このように使いたいのですが、ある日、あなたのleaderは要求レベルを上げて、アドレスの後ろにtokenパラメータを追加したり、パスワードのmd 5やsha 1の計算値を追加したりして、このニマの仕事量は小さくないと思います.もちろんurlを直接伝えることができます.
var http = {
    ajax1(url){
        url += param.getToken();
        sendAjax(url);
    },
    ajax2(url){
        ...
    }
    ...
}

そして、もしある日あなたのleaderが、ああ、このようにするのは安全性があまり高くないと言ったら、tokenを2つ加えて混同しないでください.あ~あ~あ~(妹を混同して、年を越すことができない)このように書くと、年末ボーナスはあると信じていますが、春運の汽車の切符は手が届かないと思います.従ってAOPを用いて動的織り込みが可能である.パラメータ、私のAOPも動くことができることを知っておく必要があります.
function dealUrl(url){
    url+=param.getToken();
}
http.ajax = http.ajax.before(dealUrl);
http.ajax("www.example.com");   //   Url = www.example.com?token=23jkfd3kjfdksjfkjds

そして、このurl関数を処理するには、私も任意のjsファイルに多重化することができます.すばらしい!!!私のAOPはあなたの必要なパラメータを动かすことができて、その上、私はまた私の结果をあなたにあげることができますピューピュー、もし私があなたに実行させなければ、あなたは永远に実行することができなくて、ハハハ~~~申し訳ありません、上の部分は私の意淫AOPが言ったのです..実はAOPはフォーム検証など万能な構成ツールと言えるでしょう.フォーム検証とフォーム結果送信を結合することがよくあります.こんな風に
var sendRes = function(){
    if(user.userName === ""){
        alert("       ~");
        return;
    }else if(user.password === ""){
        alert("      ~");
        return;
    }
    http.sendUser("xxx");  //          
}

1つの関数には、ユーザー情報を送信する2つの職責が同時に含まれています.だから私たちの今の主な目的は解結合です.思い出すと、以前のフォーム検証ではポリシーモードを使用し、検証をデカップリングしましたが、ここでは再び使用します.
var sendRes = function(){
    var detect = new Detect();  //     
    detect.add(user.userName,["notEmpty"]);
    detect.add(user.password,["notEmpty"]);
    var notPass = detect.getResult();
    if(notPass){  //     
        console.log(notPass);
        return;
    }
    http.sendUser("xxx"); //          
}

上記の検証は使用できますが、結果として、検証とポリシー・モードは一緒になります.さらにAOPを用いてデカップリングを行った.まずbefore関数を再構築しなければなりません
Function.prototype.before = function(fn){
    var _this = this;
    return function(){
        var res = fn.apply(this,arguments);  //  Boolean,          
        if(res==="next"){  //       ,       
            return    _this.apply(this,arguments);
        }
        return res;
    }
}

ここを見て、一部の学生は何が起こっているのか知っているはずだ.そうですね.beforeで検証した結果から、次の送信要求を実行するかどうかを判断する機能関数です.もちろん、プロトタイプを汚染したくない場合は、関数をカスタマイズすることもできます.
var before = function(beforeFn,fn){
    return function(){
        var res = beforeFn.apply(this,arguments);
        if(res==="next"){
            return fn.apply(this,arguments);
        }
    }
}

こう書いてもいいです.私たちはまず原型通りに書きます.このように直感的に書きます.
var sendRes = function(){
    http.sendUser("xxx"); //          
}
sendRes = sendRes.before(function(){
    var detect = new Detect();  //     
    detect.add(user.userName,["notEmpty"]);
    detect.add(user.password,["notEmpty"]);
    var notPass = detect.getResult();
    if(notPass){  //     
        console.log(notPass);
    }
    return "next";
});

その部分がユーザ情報を完全に送信した機能関数と完全にデカップリングされていることがわかる.これにより、関数の再利用性が向上するだけでなく、コードを「細粒度」の方向に大きく前進させることができます.

弁証装飾者モード


実は、装飾者モードと職責チェーンモードの形式は全く同じなので、彼らの弊害も似ています.チェーンが長すぎるのは、性能にとってrapeです.だから、やはりその言葉で、パターンのためにパターンを作らないでください.万能なパターンはありません.