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的惰性求值机制。

相关文章
|
2月前
|
存储 JavaScript 前端开发
JavaScript编程实现tab选项卡切换的效果+1
JavaScript编程实现tab选项卡切换的效果+1
|
6天前
|
JavaScript 前端开发 Java
[JS]同事:这次就算了,下班回去赶紧补补内置函数,再犯肯定被主管骂
本文介绍了JavaScript中常用的函数和方法,包括通用函数、Global对象函数以及数组相关函数。详细列出了每个函数的参数、返回值及使用说明,并提供了示例代码。文章强调了函数的学习应结合源码和实践,适合JavaScript初学者和进阶开发者参考。
16 2
[JS]同事:这次就算了,下班回去赶紧补补内置函数,再犯肯定被主管骂
|
5天前
|
前端开发 JavaScript 开发者
除了 Generator 函数,还有哪些 JavaScript 异步编程解决方案?
【10月更文挑战第30天】开发者可以根据具体的项目情况选择合适的方式来处理异步操作,以实现高效、可读和易于维护的代码。
|
11天前
|
自然语言处理 JavaScript 前端开发
JavaScript闭包:解锁编程潜能,释放你的创造力
【10月更文挑战第25天】本文深入探讨了JavaScript中的闭包,包括其基本概念、创建方法和实践应用。闭包允许函数访问其定义时的作用域链,常用于数据封装、函数柯里化和模块化编程。文章还提供了闭包的最佳实践,帮助读者更好地理解和使用这一强大特性。
11 2
|
19天前
|
JavaScript 前端开发
JavaScript 函数语法
JavaScript 函数是使用 `function` 关键词定义的代码块,可在调用时执行特定任务。函数可以无参或带参,参数用于传递值并在函数内部使用。函数调用可在事件触发时进行,如用户点击按钮。JavaScript 对大小写敏感,函数名和关键词必须严格匹配。示例中展示了如何通过不同参数调用函数以生成不同的输出。
|
21天前
|
存储 JavaScript 前端开发
JS函数提升 变量提升
【10月更文挑战第6天】函数提升和变量提升是 JavaScript 语言的重要特性,但它们也可能带来一些困惑和潜在的问题。通过深入理解和掌握它们的原理和表现,开发者可以更好地编写和维护 JavaScript 代码,避免因不了解这些机制而导致的错误和不一致。同时,不断提高对执行上下文等相关概念的认识,将有助于提升对 JavaScript 语言的整体理解和运用能力。
|
30天前
|
JavaScript 前端开发
js教程——函数
js教程——函数
26 4
|
29天前
|
存储 JavaScript 前端开发
js中函数、方法、对象的区别
js中函数、方法、对象的区别
15 2
|
1月前
|
JavaScript 前端开发 Java
【javaScript数组,函数】的基础知识点
【javaScript数组,函数】的基础知识点
23 5
|
1月前
|
JavaScript 前端开发
Node.js 函数
10月更文挑战第5天
19 3