JavaScript 函數自覆蓋模式

來源:互聯網
上載者:User

如果一個函數中有不少局部變數,而且並非 primitive type 的,意味著在執行該函數的時候佔用較多的記憶體開銷。這一過程是顯然易見的,例如執行這個函數 1000 次,就要重複建立那些局部變數 1000 次——這真是一個多餘的過程。再者,如果函數邏輯不會去修改局部變數的值,即屬於 constant / final 修飾的值,那麼顯然,我們僅僅建立一次變數便足夠了。好,既然如此,我們把這些可以最佳化的變數都放置函數體外面好了。雖然 js 沒有 constant / final 的修飾符,不過即使如此,那隻會僅僅影響到程式的可讀性這點不好。為最佳化這點,我們只需把變數的聲明寫到函數體外,不要寫在函數裡面。

有兩點應注意:

  1. 你可選擇不用局部變數,而是可以將變數寫成 public 屬性的調用方式,作用無異。但本文考慮的是基於替代局部變數的私人方式;
  2. 當然,這種最佳化不必然強制的,如果遇到是的簡單的字串,int……,那麼小 case 寫在函數體內倒無妨,解譯器處理很快,再最佳化可能要差別不大。總之得看情況,千萬別養成強迫症哦。

於是,我們需要考慮把這些 constant 放在何處合理的地方。通常會想到是一個閉包:

;(function(){var regExp = /d/; // 提取變數聲明語句window.isNumber = function(v){    // var regExp = /d/;            return regExp.test(v);}})();

以上是一個簡單的例子,就目的來說已經可以達到前面所說之要求了。我們利用一個閉包去儲存私人變數,這些私人變數是可以被返回的函數訪問的,但在這段代碼外面則訪問不到了。但問題是,若我們不想用閉包呢?那是一個“匿名函數”(反對使用閉包,其實也說不上究竟有什麼不好,反正覺得多了一層“怪怪”的——純屬個人感觀而言)。

這裡,我們可以大膽使用“覆蓋函數”的方式——竟然“覆蓋”?是的,別以為“覆蓋了就沒了”是一件很危險的事哦:P,請注意我們這裡是"巧用"覆蓋。

以下就是一個例子:

/** * 固定位置元素。el必須為絕對位置。 * @param {HTMLElement} el * @param {Boolean}  isOnTop 是否在最上方的,false=最下方 */$$.dhtml.fixedLayer = function(el, isOnTop){        var body  = window.document.body;        var floor = window.Math.floor;                $$.dhtml.fixedLayer = function (el, isOnTop){                var lastScrollY = isOnTop ? -20 : -(window.innerHeight - el.clientHeight - 30); /* 調整 CSS Bottom 的值 */                window.setInterval(function(){                        var percent = body.scrollTop - lastScrollY; // 移動的步伐是多大?                        percent = shiftMove(percent);                        if (percent == 0){                                return; // 0表示不滾動,位置不變,所以DOM不作變化                        }else{                                lastScrollY += percent; // 儲存位移的位置,可正可負                                addTop(el, percent);                        }                }, 10);        }                /**         * stype.top 帶單位的,運算時不方便,寫一個函數處理吧         * @private         * @param {HTMLElement} el         * @param {Number} amount         * @return {Number} 增加 amount 後此時元素的 top 值         */        function addTop(el, amount){                var top = window.parseInt(el.style.top) || 0; // style.top 有時為空白字元,那就是 = 0                top += amount;  // 弱類型的表現,先是int類型的+=                top += 'px';    // 然後這是 string 類型的!                el.style.top = top;                                return top;        }                /**         * 為更加平滑,縮小移動的步伐。         * @private         * @param {Number} percent         * @return {Number}         */        function shiftMove(percent){                percent = 0.2 * percent;                percent = floor(percent); // 取整數                                return percent;        }                return $$.dhtml.fixedLayer(el, isOnTop);}

這種的方式特點是創函數邏輯在函數內一層,第一次執行函數會覆蓋原定義的函數(被覆蓋的函數是外一層,完成了函數簽名檔作用)。函數自己覆蓋掉自己,但函數名字依舊不變,所以這一切對外如何如何調用都是透明的。如果不調用方法,函數的邏輯並不執行,頗有點類 lazyExecute 意味。

對於 hash 對象的寫法,也就是存在冒號 :  的寫法,相應的處理如 lifesinger 所示:

    createElement: function(sHtml) {        // ...        var createElement = function(sHtml) {            // ...        };        this.createElement = createElement;        return createElement(sHtml);    }

該模式的一個缺點是,如果要重新命名函數名稱,比不使用該模式多一次的操作。

實不相瞞,小弟當時也是受 lifesinger 在 zbm2001 博文之留言所啟發而至的。源地址如下:

《自訂createElement——根據html字串建立元素》http://zbm2001.iteye.com/blog/510627

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.