<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
        問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
        當前位置: 首頁 - 科技 - 知識百科 - 正文

        Javascript中的AOP編程

        來源:懂視網 責編:小采 時間:2020-11-27 20:31:23
        文檔

        Javascript中的AOP編程

        Javascript中的AOP編程: Duck punch 我們先不談AOP編程,先從duck punch編程談起。 如果你去wikipedia中查找duck punch,你查閱到的應該是monkey patch這個詞條。根據解釋,Monkey patch這個詞來源于 guerrilla patch,意為在運行中悄悄的改變代碼,而 guerril
        推薦度:
        導讀Javascript中的AOP編程: Duck punch 我們先不談AOP編程,先從duck punch編程談起。 如果你去wikipedia中查找duck punch,你查閱到的應該是monkey patch這個詞條。根據解釋,Monkey patch這個詞來源于 guerrilla patch,意為在運行中悄悄的改變代碼,而 guerril

         Duck punch

          我們先不談AOP編程,先從duck punch編程談起。

          如果你去wikipedia中查找duck punch,你查閱到的應該是monkey patch這個詞條。根據解釋,Monkey patch這個詞來源于 guerrilla patch,意為在運行中悄悄的改變代碼,而 guerrilla 這個詞與 gorilla 同音,而后者意又與monkey相近(前者為“猩猩”的意思),最后就演變為了monkey patch。

          如果你沒有聽說過duck punch,但你或許聽說過duck typing。舉一個通俗的例子,如何辨別一只鴨子:

        When I see a bird that walks like a duck and swims like a duck and quacks like a duck, I call that bird a duck.

          沒錯,如果我發現有一類動物像鴨子一樣叫,像鴨子一樣游泳,那么它就是一只鴨子!

         這個檢測看上去似乎有一些理所當然和無厘頭,但卻非常的實用。 并且在編程中可以用來解決一類問題——對于Javascript或者類似的動態語言,如何實現“接口”或者“基類”呢?我們可以完全不用在乎它們的過去如何,我們只關系在使用它們的時候,方法的類型或者參數是否是我們需要的:

        var quack = someObject.quack;
         
        if (typeof quack == "function" && quck.length == arguLength)
        {
         // This thing can quack
        }

        扯遠了,其實我想表達的是duck punch其實是由duck typing演化而來的:

        if it walks like a duck and talks like a duck, it’s a duck, right? So if this duck is not giving you the noise that you want, you’ve got to just punch that duck until it returns what you expect.

          當你想一只鴨子發出驢的叫聲怎么辦,揍到它發出驢的叫聲為止……話說這讓我想到一個非常形象的笑話:

        為了測試美國、香港、中國大陸三地警察的實力, 聯合國將三只兔子放在三個森林中,看三地警察誰先找出兔子。任務:找出兔子。 (中間省略……) 最后是某國警察,只有四個,先打了一天麻將,黃昏時一人拿一警棍進入森林,沒五分鐘,聽到森林里傳來一陣動物的慘叫,某國警察一人抽著一根煙有說有笑的出來,后面拖著一只鼻青臉腫的熊,熊奄奄一息的說到:“不要再打了,我就是兔子……”

          雖然duck punch有些暴力,但不失為一個有效的方法。落實到代碼上來說就是讓原有的代碼兼容我們需要的功能。比如Paul Irish博客上的這個例子:

        /**
         我們都知道jQuery的`$.css`方法可以通過使用顏色的名稱給元素進行顏色賦值。
         但jQuery內置的顏色并非是那么豐富,如果我們想添加我們自定義的顏色名稱應該怎么辦?比如我們想添加`Burnt Sienna`這個顏色
        */
         
        (function($){
         
         // 把原方法暫存起來:
         var _oldcss = $.fn.css;
         
         // 重寫原方法:
         $.fn.css = function(prop,value){
         
         // 把自定義的顏色寫進分支判斷里,特殊情況特殊處理
         if (/^background-?color$/i.test(prop) && value.toLowerCase() === 'burnt sienna') {
         return _oldcss.call(this,prop,'#EA7E5D');
         
         // 一般情況一般處理,調用原方法
         } else {
         return _oldcss.apply(this,arguments);
         }
         };
        })(jQuery);
         
        // 使用方法:
        jQuery(document.body).css('backgroundColor','burnt sienna')

        同時可以推倒出duck punch的模式不過如此:

        (function($){
         
         var _old = $.fn.method;
         
         $.fn.method = function(arg1,arg2){
         
         if ( ... condition ... ) {
         return ....
         } else { // do the default
         return _old.apply(this,arguments);
         }
         };
        })(jQuery);

        但是這么做有一個問題:需要修改原方法。這違背了“開放-封閉”原則,本應對拓展開放,對修改關閉。怎么解決這個問題呢?使用AOP編程。

         AOP

          入門

          AOP全稱為Aspect-oriented programming,很明顯這是相對于Object-oriented programming而言。Aspect可以翻譯為“切面”或者“側面”,所以AOP也就是面向切面編程。

          怎么理解切面?

          在面向對象編程中,我們定義的類通常是領域模型,它的擁有的方法通常是和純粹的業務邏輯相關。比如:

        Class Person
        {
         private int money;
         public void pay(int price)
         {
         this.money = this.money - price; 
         }
        }

        但通常實際情況會更復雜,比如我們需要在付款的pay方法中加入授權檢測,或者用于統計的日志發送,甚至容錯代碼。于是代碼會變成這樣:

        Class Person
        {
         private int money
         public void pay(price)
         {
         try
         {
         if (checkAuthorize() == true) {
         this.money = this.money - price; 
         sendLog();
         }
         }
         catch (Exception e)
         {
         
         } 
         }
        }

         更可怕的是,其他的方法中也要添加相似的代碼,這樣以來代碼的可維護性和可讀性便成了很大的問題。我們希望把這些零散但是公共的非業務代碼收集起來,更友好的使用和管理他們,這便是切面編程。切面編程在避免修改遠代碼的基礎上實現了代碼的復用。就好比把不同的對象橫向剖開,關注于內部方法改造。而面向對象編程更關注的是整體的架構設計。

          實現

          在上一節中介紹的duck punch與切面編程類似,都是在改造原方法的同時保證原方法功能。但就像結尾說的一樣,直接修改原方法的模式有悖于面向對象最佳實踐的原則。

          Javascript可以采用裝飾者模式(給原對象添加額外的職責但避免修改原對象)實現AOP編程。注意在這里強調的是實現,我進一步想強調的是,切面編程只是一種思想,而裝飾者模式只是實踐這種思想的一種手段而已,比如在Java中又可以采用代理模式等。切面編程在Java中發揮的余地更多,也更標準,本想把Java的實現模式也搬來這篇文章中,但不才Java水平有限,對Java的實現不是非常理解。在這里就只展示Javascript的實現。

          AOP中有一些概念需要介紹一下,雖然我們不一定要嚴格執行

        joint-point:原業務方法;

        advice:攔截方式

        point-cut:攔截方法

          關于這三個概念我們可以串起來可以這么理解:

          當我們使用AOP改造一個原業務方法(joint-point)時,比如加入日志發送功能(point-cut),我們要考慮在什么情況下(advice)發送日志,是在業務方法觸發之前還是之后;還是在拋出異常的時候,還是由日志發送是否成功再決定是否執行業務方法。

          比如gihub上的meld這個開源項目,就是一個很典型的AOP類庫,我們看看它的API:

        // 假設我們有一個對象myObject, 并且該對象有一個doSomething方法:
         
        var myObject = {
         doSomething: function(a, b) {
         return a + b;
         }
        };
         
        // 現在我們想拓展它,在執行那個方法之后打印出剛剛執行的結果:
         
        var remover = meld.after(myObject, 'doSomething', function(result) {
         console.log('myObject.doSomething returned: ' + result);
        });
         
        // 試試執行看:
         
        myObject.doSomething(1, 2); // Logs: "myObject.doSomething returned: 3"
         
        // 這個時候我們想移除剛剛的修改:
         
        remover.remove();

        由此可以看出,AOP接口通常需要三個參數,被修改的對象,被修改對象的方法(joint-point),以及觸發的時機(adivce),還有觸發的動作(point-cut)。上面說了那么多的概念,現在可能要讓各位失望了,Javascript的實現原理其實非常簡單

        function doAfter(target, method, afterFunc){
         var func = target[method];
         return function(){
         var res = func.apply(this, arguments);
         afterFunc.apply(this, arguments);
         return res; 
         };
        }

        當然,如果想看到更完備的解決方案和代碼可以參考上面所說的meld項目

         結束語

          這一篇一定讓你失望了,代碼簡單又寥寥無幾。本篇主要在于介紹有關duck和AOP的這幾類思想,我想編程的樂趣不僅僅在于落實在編碼上,更在于整個架構的設計。提高代碼的可維護性和可拓展性會比高深莫測的代碼更重要。

          其實上面

         參考文獻:

        How to Fulfill Your Own Feature Request -or- Duck Punching With jQuery!

        Duck Punching JavaScript - Metaprogramming with Prototype

        Does JavaScript have the interface type (such as Java’s ‘interface’)?

        AOP技術基礎

        聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

        文檔

        Javascript中的AOP編程

        Javascript中的AOP編程: Duck punch 我們先不談AOP編程,先從duck punch編程談起。 如果你去wikipedia中查找duck punch,你查閱到的應該是monkey patch這個詞條。根據解釋,Monkey patch這個詞來源于 guerrilla patch,意為在運行中悄悄的改變代碼,而 guerril
        推薦度:
        標簽: javascript 編程 ao
        • 熱門焦點

        最新推薦

        猜你喜歡

        熱門推薦

        專題
        Top
        主站蜘蛛池模板: 国产美女在线精品免费观看| 8x网站免费入口在线观看| 国产色婷婷精品免费视频| 亚洲同性男gay网站在线观看| 2019中文字幕在线电影免费| 91嫩草私人成人亚洲影院| 亚洲免费视频在线观看| 亚洲最大视频网站| 久久久久久国产精品免费免费| 最新国产成人亚洲精品影院| 99久久综合国产精品免费| 亚洲精品久久久久无码AV片软件| 国产精品免费看久久久无码| 一级一片免费视频播放| 国产亚洲一区二区三区在线| 免费视频爱爱太爽了| 亚洲精品人成网线在线播放va| 亚洲国产精品激情在线观看| 怡红院免费全部视频在线视频| 午夜亚洲国产理论秋霞| 日本三级2019在线观看免费| 亚洲伊人久久大香线蕉AV| 免费A级毛片在线播放不收费| 国产成人无码免费网站| 亚洲色av性色在线观无码| 在线免费一区二区| 一级毛片a免费播放王色电影| 久热综合在线亚洲精品| 毛片免费全部播放一级| 久久最新免费视频| 亚洲国产精品综合久久网各| 免费一级e一片在线播放| 国产精品99久久免费观看| 国产亚洲精aa在线看| 国产亚洲精品a在线观看 | 亚洲国产精品VA在线观看麻豆| 国产人成免费视频网站| 日本免费精品一区二区三区| 久久综合亚洲色一区二区三区| 国产成人免费片在线观看| 男人进去女人爽免费视频国产 |