zoukankan      html  css  js  c++  java
  • JavaScript惰性函数定义

    函数是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                     //skip
    16                 }
    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                         //skip
    22                     }
    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 复杂的分支判断,没有差异性,不需要应用这种模式;

  • 相关阅读:
    elastic
    Leetcode题库 第十行
    Leetcode题库-实现strStr()
    Redis持久化
    Redis的数据结构及应用场景
    Redis缓存的淘汰策略
    Redis缓存常见问题
    Redis面试题1
    消息队列的原理及选型
    【转载】java高并发/mysql/mybatis/spring博客
  • 原文地址:https://www.cnblogs.com/exhuasted/p/7474385.html
Copyright © 2011-2022 走看看