標籤:瀏覽器安全色 init 建立 內容 eve try dom time 後台
函數是js世界的一等公民,js的動態性、易變性在函數的應用上,體現的淋漓盡致。做為參數,做為傳回值等,正是函數這些特性,使得js開發變的有趣。
下面就闡述一下,js一個有趣的應用--惰性函數定義(Lazy Function Definition)。
惰性載入表示函數執行的分支只會在函數第一次掉用的時候執行,在第一次調用過程中,該函數會被覆蓋為另一個按照合適方式執行的函數,這樣任何對原函數的調用就不用再經過執行的分支了。
下面我們看幾個典型的例子:
1 function addEvent (type, element, fun) { 2 if (element.addEventListener) { 3 element.addEventListener(type, fun, false); 4 } 5 else if(element.attachEvent){ 6 element.attachEvent(‘on‘ + type, fun); 7 } 8 else{ 9 element[‘on‘ + type] = fun;10 }11 }
上面是註冊函數監聽的各瀏覽器安全色函數。由於,各瀏覽之間的差異,不得不在用的時候做能力檢測。顯然,單從功能上講,已經做到了相容瀏覽器。
美中不足,每次綁定監聽,都會對能力做一次檢測。然而,真正的應用中,這顯然是多餘的,同一個應用環境中,其實只需要檢測一次即可。
下面我們重寫上面的addEvent:
1 function addEvent (type, element, fun) { 2 if (element.addEventListener) { 3 addEvent = function (type, element, fun) { 4 element.addEventListener(type, fun, false); 5 } 6 } 7 else if(element.attachEvent){ 8 addEvent = function (type, element, fun) { 9 element.attachEvent(‘on‘ + type, fun);10 }11 }12 else{13 addEvent = function (type, element, fun) {14 element[‘on‘ + type] = fun;15 }16 }17 return addEvent(type, element, fun);18 }
由上,第一次調用addEvent會對瀏覽器做能力檢測,然後,重寫了addEvent。下次再調用的時候,由於函數被重寫,不會再做能力檢測。
同樣的應用,javascript進階程式設計裡的一例子:
1 function createXHR(){ 2 if (typeof XMLHttpRequest != "undefined"){ 3 return new XMLHttpRequest(); 4 } else if (typeof ActiveXObject != "undefined"){ 5 if (typeof arguments.callee.activeXString != "string"){ 6 var versions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0", 7 "MSXML2.XMLHttp"]; 8 9 for (var i=0,len=versions.length; i < len; i++){10 try {11 var xhr = new ActiveXObject(versions[i]);12 arguments.callee.activeXString = versions[i];13 return xhr;14 } catch (ex){15 //skip16 }17 }18 }19 20 return new ActiveXObject(arguments.callee.activeXString);21 } else {22 throw new Error("No XHR object available.");23 }24 }
很顯然,惰性函數在這裡優勢更加明顯,因為這裡有更多的分支。下面我們看一下重寫背景函數:
1 function createXHR() { 2 if (typeof XMLHttpRequest != "undefined") { 3 createXHR = function () { 4 return new XMLHttpRequest(); 5 } 6 return new XMLHttpRequest(); 7 } else if (typeof ActiveXObject != "undefined") { 8 var curxhr; 9 var versions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0",10 "MSXML2.XMLHttp"];11 12 for (var i = 0, len = versions.length; i < len; i++) {13 try {14 var xhr = new ActiveXObject(versions[i]);15 curxhr = versions[i];16 createXHR = function () {17 return new ActiveXObject(curxhr);18 }19 return xhr;20 } catch (ex) {21 //skip22 }23 }24 } else {25 throw new Error("No XHR object available.");26 }27 }
瀏覽器之間最大的差異,莫過於Dom操作,Dom操作也是前端應用 中最頻繁的操作,前端的大多效能提升,均體現在Dom操作方面。
下面看一個Dom操作方面的惰性函數定義例子:
1 var getScrollY = function() { 2 3 if (typeof window.pageYOffset == ‘number‘) { 4 5 getScrollY = function() { 6 return window.pageYOffset; 7 }; 8 9 } else if ((typeof document.compatMode == ‘string‘) &&10 (document.compatMode.indexOf(‘CSS‘) >= 0) &&11 (document.documentElement) &&12 (typeof document.documentElement.scrollTop == ‘number‘)) {13 14 getScrollY = function() {15 return document.documentElement.scrollTop;16 };17 18 } else if ((document.body) &&19 (typeof document.body.scrollTop == ‘number‘)) {20 21 getScrollY = function() {22 return document.body.scrollTop;23 }24 25 } else {26 27 getScrollY = function() {28 return NaN;29 };30 31 }32 33 return getScrollY();34 }
惰性函數定義應用還體現在建立單例上:
1 unction Universe() { 2 3 // 緩衝的執行個體 4 var instance = this; 5 6 // 其它內容 7 this.start_time = 0; 8 this.bang = "Big"; 9 10 // 重寫建構函式11 Universe = function () {12 return instance;13 };14 }
當然,像上面這種例子有很多。惰性函數定義,應用情境我們可以總結一下:
1 應用頻繁,如果只用一次,是體現不出它的優點出來的,用的次數越多,越能體現這種模式的優勢所在;
2 固定不變,一次判定,在固定的應用環境中不會發生改變;
3 複雜的分支判斷,沒有差異性,不需要應用這種模式;
JavaScript惰性函數定義