穆乙: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 复杂的分支判断,没有差别性,不须要应用这种模式;