惰性函数定义模式 使用方法第2/3页

 更新时间:2007年09月20日 19:55:43   作者:  

方法四:惰性函数定义
现在,这是你阅读这篇文章的理由:
复制代码 代码如下:

var foo = function() { 
    var t = new Date(); 
    foo = function() { 
        return t; 
    }; 
    return foo(); 
}; 

当foo首次调用,我们实例化一个新的Date对象并重置 foo到一个新的函数上,它在其闭包内包含Date对象。在首次调用结束之前,foo的新函数值也已调用并提供返回值。

接下来的foo调用都只会简单地返回t保留在其闭包内的值。这是非常快的查找,尤其是,如果之前那些例子的条件非常多和复杂的话,就会显得很高效。

弄清这种模式的另一种途径是,外围(outer)函数对foo的首次调用是一个保证(promise)。它保证了首次调用会重定义foo为一个非常有用的函数。笼统地说,术语“保证” 来自于Scheme的惰性求值机制(lazy evaluation mechanism)。每一位JavaScript程序员真的都应该 学习Scheme ,因为它有很多函数式编程相关的东西,而这些东西会出现在JavaScript中。

确定页面滚动距离

编写跨浏览器的JavaScript, 经常会把不同的浏览器特定的算法包裹在一个独立的JavaScript函数中。这就可以通过隐藏浏览器差异来标准化浏览器API,并让构建和维护复杂的页面特性的JavaScript更容易。当包裹函数被调用,就会执行恰当的浏览器特定的算法。

在拖放库中,经常需要使用由鼠标事件提供的光标位置信息。鼠标事件给予的光标坐标相对于浏览器窗口而不是页面。加上页面滚动距离鼠标的窗口坐标的距离即可得到鼠标相对于页面的坐标。所以我们需要一个反馈页面滚动的函数。演示起见,这个例子定义了一个函数getScrollY。因为拖放库在拖拽期间会持续运行,我们的getScrollY必须尽可能高效。

不过却有四种不同的浏览器特定的页面滚动反馈算法。Richard Cornford在他的feature detection article 文章中提到这些算法。最大的陷阱在于这四种页面滚动反馈算法其中之一使用了 document.body. JavaScript库通常会在HTML文档的<head>加载,与此同时docment.body并不存在。所以在库载入的时候,我们并不能使用特性检查(feature detection)来确定使用哪种算法。

考虑到这些问题,大部分JavaScript库会选择以下两种方法中的一种。第一个选择是使用浏览器嗅探navigator.userAgent,为该浏览器创建高效、简洁的getScrollY. 第二个更好些的选择是getScrollY在每一次调用时都使用特性检查来决定合适的算法。但是第二个选择并不高效。

好消息是拖放库中的getScrollY只会在用户与页面的元素交互时才会用到。如果元素业已出现在页面中,那么document.body也会同时存在。getScrollY的首次调用,我们可以使用惰性函数定义模式结合特性检查来创建高效的getScrollY.
复制代码 代码如下:

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(); 


相关文章

  • JS获取表格视图所选行号的ids过程解析

    JS获取表格视图所选行号的ids过程解析

    这篇文章主要介绍了JS获取表格视图所选行号的ids过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-02-02
  • JS跳出循环的方法区别对比分析(break,continue,return)

    JS跳出循环的方法区别对比分析(break,continue,return)

    面向对象编程语法中我们会碰到break ,continue, return这三个常用的关键字,那么关于这三个关键字的使用具体的操作是什么呢?接下来通过本文给大家讲解JS跳出循环的方法区别对比分析(break,continue,return),感兴趣的朋友一起看看吧
    2023-02-02
  • 前端实现多个内容滑动轮播图效果实例

    前端实现多个内容滑动轮播图效果实例

    在前端开发中,滑动轮播图是一种常见的交互元素,用于展示多张图片或内容,这篇文章主要介绍了前端实现多个内容滑动轮播图效果的相关资料,文中给出了详细的代码示例,需要的朋友可以参考下
    2025-04-04
  • package.json与package-lock.json的区别及详细解释

    package.json与package-lock.json的区别及详细解释

    不知道大家平时在开发中有没有注意到,你的项目中有两个文件:package.json,package-lock.json,应该很多人平时都不会去关注这两个文件有啥关系吧,这篇文章主要给大家介绍了关于package.json与package-lock.json的区别及详细解释,需要的朋友可以参考下
    2022-08-08
  • JavaScript删除数组元素的方法

    JavaScript删除数组元素的方法

    这篇文章主要介绍了JavaScript删除数组元素的方法,实例分析了javascript中delete函数的使用技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-03-03
  • JS实现十字坐标跟随鼠标效果

    JS实现十字坐标跟随鼠标效果

    这篇文章给大家分享一下通过JS实现十字坐标跟随鼠标效果的代码,有需要的朋友参考学习下吧。
    2017-12-12
  • javascript中callee与caller的区别分析

    javascript中callee与caller的区别分析

    有些小伙伴可能会问caller,callee 是什么?在javascript 中有什么样的作用?那么本篇会对于此做一些基本介绍。希望能够对大家理解javascript中的callee与caller有所帮助。
    2015-04-04
  • 基于bootstrap写的一点localStorage本地储存

    基于bootstrap写的一点localStorage本地储存

    这篇文章主要介绍了基于bootstrap写的一点localStorage本地储存,需要的朋友可以参考下
    2017-11-11
  • Sublime Text 3常用插件及安装方法

    Sublime Text 3常用插件及安装方法

    这篇文章主要介绍了Sublime Text 3常用插件及安装方法的相关资料,需要的朋友可以参考下
    2015-12-12
  • js判断浏览器是否支持严格模式的方法

    js判断浏览器是否支持严格模式的方法

    除了正常运行模式,ECMAscript 5添加了第二种运行模式:"严格模式"(strict mode)。顾名思义,这种模式使得Javascript在更严格的条件下运行。这篇文章给大家详细介绍了js判断浏览器是否支持严格模式的方法,有需要的朋友们可以参考借鉴。
    2016-10-10

最新评论