JS编程建议——65:比较函数的惰性求值与非惰性求值

简介: 65:比较函数的惰性求值与非惰性求值

建议65:比较函数的惰性求值与非惰性求值
在JavaScript中,使用函数式风格编程时,应该对于表达式有着深刻的理解,并能够主动使用表达式的连续运算来组织代码。
1)在运算元中,除了JavaScript默认的数据类型外,函数也作为一个重要的运算元参与运算。
2)在运算符中,除了JavaScript的大量预定义运算符外,函数还作为一个重要的运算符进行计算和组织代码。
函数作为运算符参与运算,具有非惰性求值特性。非惰性求值行为自然会对整个程序产生一定的负面影响。先看下面这个示例:
var a = 2;
function f(x){

return x;

}
alert(f(a,a=a*a)); //2
alert(f(a)); //4
在上面的示例中,两次调用同一个函数并传递同一个变量,所返回的值却不一样。在第一次调用函数时,向其传递了两个参数,第二个参数是一个表达式,该表达式对变量a进行重新计算和赋值。也就是说,当调用函数时,第二个参数虽然不使用,但是也被计算了。这就是JavaScript的非惰性求值特性,也就是说,不管表达式是否被利用,只要在执行代码行中都会被计算。
如果在一个函数参数中无意添加了几个表达式,虽然这样不会对函数的运算结果产生影响,但是由于表达式被执行,就会对整个程序产生潜在的负面影响。
在惰性求值语言中,如果参数不被调用,那么无论参数是直接量还是某个表达式,都不会占用系统资源。但是,由于JavaScript支持非惰性求值,问题就变得很特殊了。
function f(){}
f( function(){while(true);}())
在上面的示例中,虽然函数f没有参数,但是在调用时将会执行传递给它的参数表达式,该表达式是一个死循环结构的函数值,最终将导致系统崩溃。
惰性函数模式是一种将对函数或请求的处理延迟到真正需要结果时进行的通用概念,很多应用程序都采用了这种概念。从惰性编程的角度来思考问题,可以帮助消除代码中不必要的计算。例如,在Scheme语言中,delay特殊表单接收一个代码块,它不会立即执行这个代码块,而是将代码和参数作为一个promise存储起来。如果需要promise产生一个值,就会运行这段代码。promise 随后会保存结果,这样将来再请求这个值时,该值就可以立即返回,而不用再次执行代码。这种设计模式在JavaScript中大有用处,尤其是在编写跨浏览器的、高效运行的库时非常有用。例如,下面是一个时间对象实例化的函数。
var t;
function f(){

t = t ? t : new Date();
return t;

}
f(); // 调用函数
上面的示例使用全局变量t来存储时间对象,这样在每次调用函数时都必须进行重新求值,代码的效率没有得到优化,同时全局变量t很容易被所有代码访问和操作,存在安全隐患。当然,可以使用闭包隐藏全局变量t,只允许在函数f内访问。
var f =(function(){

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

})();
f();
这仍然没有提高调用时的效率,因为每次调用f依然需要求值:
var f = function() {

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

};
f();
在上面的示例中,函数f的首次调用将实例化一个新的Date对象并重置f到一个新的函数上,f在其闭包内包含Date对象。在首次调用结束之前,f的新函数值也已被调用并提供返回值。
函数f的调用都只会简单地返回t保留在其闭包内的值,这样执行起来非常高效。弄清这种模式的另一种途径是,外部函数f的首次调用是一个保证(promise),它保证了首次调用会重定义f为一个非常有用的函数,保证来自于Scheme的惰性求值机制。

相关文章
|
6天前
|
存储 JavaScript 前端开发
JavaScript编程实现tab选项卡切换的效果+1
JavaScript编程实现tab选项卡切换的效果+1
|
8天前
|
JavaScript 前端开发 安全
JavaScript函数详解
JavaScript函数的详细解析,包括函数的定义和调用方式(如一般格式、匿名函数、构造函数、自调用函数、箭头函数和严格模式)、函数参数(arguments对象、可变参数、默认参数值)、闭包的概念和应用实例。
JavaScript函数详解
|
7天前
|
JavaScript 前端开发
JavaScript函数可以返回两个值
JavaScript函数可以返回两个值
|
7天前
|
自然语言处理 分布式计算 JavaScript
JavaScript函数
JavaScript函数
|
10天前
|
JSON JavaScript 数据格式
手写JS实现深拷贝函数
本文介绍了如何实现一个深拷贝函数`deepClone`,该函数可以处理对象和数组的深拷贝,确保拷贝后的对象与原始对象在内存中互不干扰。通过递归处理对象的键值对和数组的元素,实现了深度复制,同时保留了函数类型的值和基础类型的值。
15 3
|
8天前
|
缓存 JavaScript 前端开发
了解js基础知识中的作用域和闭包以及闭包的一些应用场景,浅析函数柯里化
该文章详细讲解了JavaScript中的作用域、闭包概念及其应用场景,并简要分析了函数柯里化的使用。
了解js基础知识中的作用域和闭包以及闭包的一些应用场景,浅析函数柯里化
|
10天前
|
前端开发 数据可视化 开发者
D3.js 内置的动画函数
D3.js 内置的动画函数
|
11天前
|
JavaScript 前端开发
JavaScript 函数参数
JavaScript 函数参数
23 3
|
11天前
|
存储 JavaScript 前端开发
JavaScript 函数定义
JavaScript 函数定义
17 3
|
10天前
|
JavaScript 前端开发
js防抖函数返回值问题解决方案
本文介绍了如何在JavaScript中创建一个带有返回值的防抖函数,通过结合Promise来实现。这种防抖函数可以在事件触发一定时间后再执行函数,并能处理异步操作的返回值。文章提供了防抖函数的实现代码和如何在实际项目中使用该防抖函数的示例。
16 1