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

这篇文章阐述的是一种函数式编程(functional-programming)设计模式,我称之为惰性函数定义(Lazy Function Definition)。我不止一次发现这种模式在JavaScript中大有用处,尤其是编写跨浏览器的、高效运行的库之时。

热身问题

编写一个函数foo,它返回的是Date对象,这个对象保存的是foo首次调用的时间。

方法一:上古时代的技术

这个最简陋的解决方案使用了全局变量t来保存Date对象。foo首次调用时会把时间保存到t中。接下来的再次调用,foo只会返回保存在t中的值。


代码如下:

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

但是这样的代码有两个问题。第一,变量t是一个多余的全局变量,并且在 foo调用的间隔期间有可能被更改。第二,在调用时这些代码的效率并没有得到优化因为每次调用 foo都必须去求值条件。虽然在这个例子中,求值条件并不显得低效,但在现实世界的实践例子中常常会有极为昂贵的条件求值,比如在if-else-else-…的结构中。

方法二:模块模式

我们可以通过被认为归功于Cornford 和 Crockford 的模块模式来弥补第一种方法的缺陷。使用闭包可以隐藏全局变量t,只有在 foo内的代码才可以访问它。

代码如下:

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

但这仍然没有优化调用时的效率,因为每次调用foo依然需要求值条件。
虽然模块模式是一个强大的工具,但我坚信在这种情形下它用错了地方。
方法三:函数作为对象
由于JavaScript的函数也是对象,所以它可以带有属性,我们可以据此实现一种跟模块模式质量差不多的解决方案。

代码如下:

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

在一些情形中,带有属性的函数对象可以产生比较清晰的解决方案。我认为,这个方法在理念上要比模式模块方法更为简单。

这个解决方案避免了第一种方法中的全局变量t,但仍然解决不了foo每次调用所带来的条件求值。

当前1/3页 123下一页阅读全文

(0)

相关推荐

  • JavaScript 函数惰性载入的实现及其优点介绍

    最近看JavaScript高级程序设计,大有收获,接下来几天写一下读书笔记.之前写了一篇Ajax初步理解的随笔,里面有个函数用来创建XmlHttpRequest对象,浏览器兼容性原因,写出的代码通过大量if判断或者try,catch语句将函数引导到正确代码处. 复制代码 代码如下: <script type="text/javascript"> function createXHR(){ var xhr = null; try { // Firefox, Opera 8.0

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

    这篇文章阐述的是一种函数式编程(functional-programming)设计模式,我称之为惰性函数定义(Lazy Function Definition).我不止一次发现这种模式在JavaScript中大有用处,尤其是编写跨浏览器的.高效运行的库之时. 热身问题 编写一个函数foo,它返回的是Date对象,这个对象保存的是foo首次调用的时间. 方法一:上古时代的技术 这个最简陋的解决方案使用了全局变量t来保存Date对象.foo首次调用时会把时间保存到t中.接下来的再次调用,foo只会返

  • JavaScript eval()函数定义及使用方法详解

    定义和用法 eval() 函数可计算某个字符串,并执行其中的的 JavaScript 代码. 语法 eval(string) 返回值 通过计算 string 得到的值(如果有的话). 说明 该方法只接受原始字符串作为参数,如果 string 参数不是原始字符串,那么该方法将不作任何改变地返回.因此请不要为 eval() 函数传递 String 对象来作为参数. 如果试图覆盖 eval 属性或把 eval() 方法赋予另一个属性,并通过该属性调用它,则 ECMAScript 实现允许抛出一个 Ev

  • php实现的统计字数函数定义与使用示例

    本文实例讲述了php实现的统计字数函数定义与使用方法.分享给大家供大家参考,具体如下: <?php //函数定义: function countWords($str){ echo (mb_strlen($str, 'utf8') + strlen($str))/2; } //使用方法: $strdemo1='欢迎访问我们'; $strdemo2='http://www.jb51.net'; $strdemo3='欢迎访问我们http://www.jb51.net'; countWords($st

  • JS函数的定义与调用方法推荐

    JS函数调用的四种方法:方法调用模式,函数调用模式,构造器调用模式,apply,call调用模式 1. 方法调用模式: 先定义一个对象,然后在对象的属性中定义方法,通过myobject.property来执行方法,this即指当前的myobject对象. var blogInfo={ blogId:123, blogName:"werwr", showBlog:function(){alert(this.blogId);} }; blogInfo.showBlog(); 2. 函数调用

  • vue项目中定义全局变量、函数的几种方法

    前言 在项目中,经常会复用一些变量和函数,比如用户的登录token,用户信息等.这时将它们设为全局的就显得很重要了,全局变量和全局函数之间有一些相通之处,它们其实很简单,但是有些人可能还不太了解.简单总结分享一波,希望对你有所帮助. 定义全局变量 原理:使用模块(.js或.vue文件)来管理全局变量,最后使用export暴露出去 (最好导出的格式为对象,方便在其他地方调用),当其它地方需要使用时,用import导入该模块 1.使用全局变量专用模块,挂载到main.js文件上面 全局变量模块Glo

  • AngularJS中控制器函数的定义与使用方法示例

    本文实例讲述了AngularJS中控制器函数的定义与使用方法.分享给大家供大家参考,具体如下: HTML正文: <body ng-app="myApp" ng-controller="myCtrl"> <h2>AngularJS函数绑定</h2> <textarea ng-model="message" cols="40" rows="10"></tex

  • JavaScript中定义函数的三种方法

    在JavaScript的世界里,定义函数的方法多种多样,这正是JavaScript灵活性的体现,但是正是这个原因让初学者摸不着头脑,尤其对于没有 语言基础的同学.正所谓条条大道通罗马,但是如果道路太多,会让行路者不知所措,因为不知道走那条路才是正途,呵呵,废话一大篇,闲言少叙,先看代码: 复制代码 代码如下: /*第一种方法,使用function语句,格式如下*/ function fn(){ alert("这是使用function语句进行函数定义"); } fn(); /*第二种方法

  • CakePHP框架Model函数定义方法示例

    本文实例讲述了CakePHP框架Model函数定义方法.分享给大家供大家参考,具体如下: 在CakePHP中,MVC的架构是清晰的,而在实际做项目中,我发现仍然有很多人喜欢在Controller中堆砌函数,这样做也未尝不可,但是,作为一个百万行级的大项目来说,这种违背MVC思想的做法虽然可能暂时给程序结构带来便利,但从长远来看,是万万不可取的! 我们应该将系统常用到的某些函数定义在Model中,特别是纯粹的的数据处理函数和数据查询函数: 譬如,在Blog中像下面这样的条件查询: /* * * B

  • C++中可以接受任意多个参数的函数定义方法(详解)

    能够接受任意多个参数的函数,可以利用重载来实现.这种函数的执行过程类似于递归调用,所以必须要有递归终止条件. #include <iostream> #include <bitset> void print() {} // 递归终止条件.这是必需的. template<typename Type, typename... Types> void print(const Type& arg, const Types&... args) { std::cou

  • php 函数使用方法与函数定义方法

    对于一个函数的语法是: 函数定义方法 复制代码 代码如下: function "function_name" (arg1, arg2...) { [code to execute] return [final_result]; } 其中[final_result]通常是从函数返回变量值. 让我们看一个例子 复制代码 代码如下: function double_this_number($input_number) { return $input_number*2; } 调用方法 复制代码

随机推荐