穆乙:http://www.cnblogs.com/pigtail/p/3447660.html javascript
函數是js世界的一等公民,js的動態性、易變性在函數的應用上,體現的淋漓盡致。作爲參數,作爲返回值等,正是函數這些特性,使得js開發變的有趣。html
下面就闡述一下,js一個有趣的應用--惰性函數定義(Lazy Function Definition)。前端
惰性載入表示函數執行的分支只會在函數第一次掉用的時候執行,在第一次調用過程當中,該函數會被覆蓋爲另外一個按照合適方式執行的函數,這樣任何對原函數的調用就不用再通過執行的分支了。java
下面咱們看幾個典型的例子:瀏覽器
function addEvent (type, element, fun) { if (element.addEventListener) { element.addEventListener(type, fun, false); } else if(element.attachEvent){ element.attachEvent('on' + type, fun); } else{ element['on' + type] = fun; } }
上面是註冊函數監聽的各瀏覽器兼容函數。因爲,各瀏覽之間的差別,不得不在用的時候作能力檢測。顯然,單從功能上講,已經作到了兼容瀏覽器。美中不足,每次綁定監聽,都會對能力作一次檢測。然而,真正的應用中,這顯然是多餘的,同一個應用環境中,其實只須要檢測一次便可。緩存
下面咱們重寫上面的addEvent:函數
function addEvent (type, element, fun) { if (element.addEventListener) { addEvent = function (type, element, fun) { element.addEventListener(type, fun, false); } } else if(element.attachEvent){ addEvent = function (type, element, fun) { element.attachEvent('on' + type, fun); } } else{ addEvent = function (type, element, fun) { element['on' + type] = fun; } } return addEvent(type, element, fun); }
由上,第一次調用addEvent會對瀏覽器作能力檢測,而後,重寫了addEvent。下次再調用的時候,因爲函數被重寫,不會再作能力檢測。性能
一樣的應用,javascript高級程序設計裏的一例子:this
function createXHR(){ if (typeof XMLHttpRequest != "undefined"){ return new XMLHttpRequest(); } else if (typeof ActiveXObject != "undefined"){ if (typeof arguments.callee.activeXString != "string"){ var versions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0", "MSXML2.XMLHttp"]; for (var i=0,len=versions.length; i < len; i++){ try { var xhr = new ActiveXObject(versions[i]); arguments.callee.activeXString = versions[i]; return xhr; } catch (ex){ //skip } } } return new ActiveXObject(arguments.callee.activeXString); } else { throw new Error("No XHR object available."); } }
很顯然,惰性函數在這裏優點更加明顯,由於這裏有更多的分支。下面咱們看一下重寫後臺的函數:spa
function createXHR() { if (typeof XMLHttpRequest != "undefined") { createXHR = function () { return new XMLHttpRequest(); } return new XMLHttpRequest(); } else if (typeof ActiveXObject != "undefined") { var curxhr; var versions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0", "MSXML2.XMLHttp"]; for (var i = 0, len = versions.length; i < len; i++) { try { var xhr = new ActiveXObject(versions[i]); curxhr = versions[i]; createXHR = function () { return new ActiveXObject(curxhr); } return xhr; } catch (ex) { //skip } } } else { throw new Error("No XHR object available."); } }
瀏覽器之間最大的差別,莫過於Dom操做,Dom操做也是前端應用 中最頻繁的操做,前端的大多性能提高,均體如今Dom操做方面。下面看一個Dom操做方面的惰性函數定義例子:
var getScrollY = function() { if (typeof window.pageYOffset == 'number') { getScrollY = function() { return window.pageYOffset; }; } else if ((typeof document.compatMode == 'string') && (document.compatMode.indexOf('CSS') >= 0) && (document.documentElement) && (typeof document.documentElement.scrollTop == 'number')) { getScrollY = function() { return document.documentElement.scrollTop; }; } else if ((document.body) && (typeof document.body.scrollTop == 'number')) { getScrollY = function() { return document.body.scrollTop; } } else { getScrollY = function() { return NaN; }; } return getScrollY(); }
惰性函數定義應用還體如今建立單例上:
unction Universe() { // 緩存的實例 var instance = this; // 其它內容 this.start_time = 0; this.bang = "Big"; // 重寫構造函數 Universe = function () { return instance; }; }
固然,像上面這種例子有不少。惰性函數定義,應用場景咱們能夠總結一下:
1 應用頻繁,若是隻用一次,是體現不出它的優勢出來的,用的次數越多,越能體現這種模式的優點所在;
2 固定不變,一次斷定,在固定的應用環境中不會發生改變;
3 複雜的分支判斷,沒有差別性,不須要應用這種模式;