`
zuroc
  • 浏览: 1302318 次
  • 性别: Icon_minigender_1
  • 来自: 江苏
社区版块
存档分类
最新评论

JS:惰性函数定义?不是最优化方案

阅读更多
Lazy Function Definition Pattern
js函数式编程中的一种设计模式

http://realazy.org/blog/2007<wbr></wbr>/08/16/lazy-function-definitio<wbr></wbr>n-pattern/
惰性函数定义模式的中文翻译

我认为没什么用,还有内存泄露,我这样写
function foo() {
    return this.date||(this.date=Date());
   return foo.date||(foo.date=Date());
};

function foo(){
var c=arguments.callee;
return c.date=c.date||Date();
}

my={
    foo:function () {
        return this._date||(this._date=Date()); 
    }
}
或约定一下
var _foo_date;
function foo(){
return _foo_date=_foo_date||Date();
}

1.代码精悍
2.没有泄露
这种小对象的内存泄露一般不会很大,可以忽略.

当作用于有大量子元素的dom节点时,这种泄漏就会累加到一个恐怖的地步.对于类似GoogleReader这类应用常常会遇到类似问题

3.解决了foo每次调用所带来的条件求值
分享到:
评论
10 楼 hax 2007-08-18  
误操作,删之。。。
9 楼 hax 2007-08-18  
我在最近几个帖子里谈到过性能问题只有以下几个:

1. 这个在第一次调用时重新定义自己的pattern,不可能带来 significant 的性能提升(如果不是反而降低的话)。

2. 如果我没有记错,根据 Brendan Eich 的说法,总体来说closure比通常方法要多耗三倍内存,慢三倍。至于他是怎么得出这个结论的,请自行mail问之。不过鉴于他的身份,偶是比较相信他的话的。

3. 关于closure对垃圾回收的影响,请阅读我的帖子:http://hax.iteye.com/blog/113565
8 楼 radar 2007-08-18  
function outerFun(a){
    function innerFun(p){
        return a+p;
    }
    return function(p){
        return innerFun(p);
    }
}
alert(outerFun(2)(2)) //最理想用法
var f=outerFun(3);    //这样用呢
var f1=outerFun(4);  //这样用呢 hax 说的性能问题是这吗?
alert(f(2))
alert(f1(2))

无closure,无innerFunction的代码性能最高?
如果把所有附值语句都去掉呢?
谁最节约内存呢?
7 楼 radar 2007-08-18  
首先我是从ajaxian看到这篇文章呢。这个标题太容易让人误解,和FP没什么关系。
我觉得可以分为两个层面内容:
1、cache。你的date无论怎么看都是一个cahce的应用。当第一次得到结果时,计算值。
   这种情况,cache放到哪我觉得无所谓。是约定问题。当系统中有大量的这种应用时,放心,自然而然  解决cache的模式就有了。
2、getScollX那个应用和date的不同,而是自己修改自己,不重在名称空间污染的情况。
6 楼 zuroc 2007-08-18  
Beag.Ye 写道
zuroc 写道
错误已修正

本质上没变啊,只是把这个名字空间换成了那个名字空间而已,等同相当于方案三,或者更怪。
JS1.5 中只有闭包代换才能保证安全,一点类似 Lich_Ray 给出的纯恶搞的代码就能崩了它,所以祈祷吧


js中无法限制写纯恶搞的代码,如下,还是在服务器端限制吧

var foo=function (){
alert("正常运行")
}
document.body.onclick=foo

//恶意代码
var foo=function (){
alert("黑客入侵")
}
document.body.onclick=foo
5 楼 hax 2007-08-18  
楼主确实原来犯了一个低级错误,呵呵。
此外,用 || 短路操作,存在一个问题,就是计算结果可能为false, 0, null, ''的情况,结果每次调用都会重新计算一遍。当然这个Date的小例子里不存在,但是很值得警惕哦。所以比较严谨的写法,还是不要省略这若干个字符,写成:

if ('_cache' in argument.callee) return argument.callee._cache;


To Realazy:
在我之后,fckeditor的人好像有个回帖,意思跟我接近。Peter自己有回帖,表示要update,你可以看看,是否也更新一下你的翻译,呵呵。

To Lich_Ray:
不是我要跟你较真,但这个closure内存泄露,不单单是实现层的问题。一个是,ECMA规范里完全没有要求对这种情况的优化。因此编程的前提若是这种不太可靠的优化,就不是很妥当,事实上,现在似乎也没有js引擎做了这种优化。我个人猜测,编译型的js引擎,比较可能去作这种优化,例如rhino的编译成java类,以及actionscript,谁有兴趣可以去测试看看。
而就算一个最出色的优化过的引擎,只要closure内部存在动态eval,理论上所有scopechain上的变量都不可能被优化掉。

所以从当前实践的角度出发,这种内存泄露,是编程造成的。只能希望以后,我们可以没有这个负担。

另外,我没有说过这个方法性能消耗大到人人喊大,我只是指出这个方法并没有提供什么性能优势,同时容易造成内存泄露的事实。关于你说的安全性,我猜测你是指function对象上的cache可能被外部代码破坏。不错,理论上确实如此,但实际中,通过一个良好的命名规范,是可以在实践上避免的。

况且,我只是指出问题,并没有完全否定closure的使用。在实际编程中,我也一样疯狂的使用closure,一样疯狂的热爱functional的方式。我所在开发的PIES框架中,核心的module/package功能就是靠创造许多的closure,再用上许多邪恶的with来达到的。

我所表达的意思,其实无非是使用closure的时候你也要注意一下,有些时候没有必要一定用closure,有些时候需要谨慎考虑一下closure外面变量的生命周期。

还有,说到functional,其实像重新改写自身(改变了binding)这种事情,是违背functional的精神的。这也是我对于qomo的AOP实现的批评之一,它悄悄的把你的方法给替换了,名字一样,表面看上去没有变化,但对象已经不是那个对象了(放在现实世界中可以拍电影了,参考《face off》,呵呵)。这种事情其实是存在危险的。

BTW,楼主虽然犯了低级错误,但也不至于拿退出js圈子相威胁吧?你咋不宣称要退出javaeye呢,呵呵?


4 楼 Beag.Ye 2007-08-18  
zuroc 写道
错误已修正

本质上没变啊,只是把这个名字空间换成了那个名字空间而已,等同相当于方案三,或者更怪。
JS1.5 中只有闭包代换才能保证安全,一点类似 Lich_Ray 给出的纯恶搞的代码就能崩了它,所以祈祷吧
3 楼 zuroc 2007-08-18  
错误已修正
2 楼 Lich_Ray 2007-08-17  
hax 说的“内存泄漏”仅是实现层的问题。而LZ的代码根本就是错的,其实用了一个全局变量:
js> date = 9
9
js> function foo() {
   return this.date||(this.date=Date());
};
js> foo()
9

还不如方案一。就算运气好点,原本 date 为一个假值,this 引用也会污染上层名字空间。
js> date = 0
0
js> foo()
Fri Aug 17 2007 20:30:42 GMT+0800 (CST)
js> date
Fri Aug 17 2007 20:30:42 GMT+0800 (CST)

看得我都有从 javascript研究小组 退组的想法了。

To hax: Lazy 版函数决不是什么新东西,但性能消耗还没上升到人人喊打的地步,安全性是值得称赞的。
1 楼 Realazy 2007-08-17  
我只能用作者的话回复你:

Your example is nice and short and you don’t refer to foo twice. I debated about using a a couple different compact forms for the warm-up exercise but solutions in real examples never seem take the same compact forms.

相关推荐

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

    惰性函数定义模式是函数式编程中的一种设计模式,它主要应用于提高程序的效率和减少不必要的计算。在JavaScript中,这种模式尤其适用于编写高性能的库,因为它能够确保函数的计算只在真正需要时进行,而不是在函数...

    一本关于JavaScript中函数式编程的书

    这种方式可以使代码更加模块化,每个函数只关注一个特定任务,而整个流程由组合函数定义。 五、柯里化 柯里化是将接受多个参数的函数转换为一系列接受单个参数的函数的过程。这样可以提前部分应用参数,创建具名的...

    同步函数编程_synchronous functional programming

    6. **尾调用优化**:JavaScript ES6引入了尾调用优化,允许在函数的最后一步调用自身,避免栈溢出,提升性能。虽然这个特性在严格模式下默认关闭,但了解其原理可以帮助编写更高效的代码。 7. **函数式数据结构**:...

    FuncProgTalk:函数式编程讲座与 Javascript 代码示例

    JavaScript 中,我们可以定义纯函数来处理数据,如数组的map、filter和reduce等方法。 2. **高阶函数**:高阶函数可以接受一个或多个函数作为参数,或者返回一个函数作为结果。例如,`Array.prototype.map`就是高阶...

    傻瓜函数式编程.docx

    7. **惰性求值(Lazy Evaluation)**:只有在需要时才计算表达式的值,可以优化性能,特别是在处理大数据时。 8. **闭包**:函数可以记住其定义时的作用域,即使在该作用域不再存在时也能访问其变量,提供了一种...

    JavaScript惰性求值的一种实现方法示例

    文件内容最后指出,惰性求值的实现是通过迭代器和生成器完成的,这可能需要读者对JavaScript中的迭代器协议和生成器函数有一定的了解。在实际编码时,开发者可能需要处理一些边界情况,比如数据流的终止条件,以及...

    js代码-JavaScript 函数式编程

    3. **闭包**:JavaScript中的闭包是指有权访问另一个函数作用域中的变量的函数,创建闭包的常见方式是在一个函数内部定义另一个函数。闭包常用于实现私有变量和模块化。 ```javascript function outer() { let ...

    javascript-playbook:一个定义我们使用 JavaScript 的约定的地方

    JavaScript是世界上最受欢迎的编程语言之一,特别是在Web开发领域。`javascript-playbook`是一个项目,它为使用JavaScript编程提供了一套约定和最佳实践。这个资源旨在帮助开发者建立一致、可维护和高效的代码库。 ...

    functional-js

    5. **闭包**:JavaScript的闭包特性允许函数访问并操作其词法作用域内的变量,即使在其外部定义。这在实现局部状态管理和模块化时非常有用。 6. **尾调用优化**:JavaScript引擎对尾调用的优化可以避免深度嵌套的回...

    functional-javascript-workshop:功能性javascript-workshop的解决方案

    6. **函数式数据结构**:在JavaScript中,虽然数组和对象不是纯函数式语言中的不可变数据结构,但我们可以使用库如Lodash或Ramda来模仿这些特性。不可变数据避免了副作用,提高了代码的安全性和可测试性。 7. **...

    javascript中最常用的55个经典技巧

    JavaScript,作为全球最广泛使用的编程语言之一,是创建交互式网页和应用程序的关键工具。这篇关于“JavaScript中最常用的55个经典技巧”的文章旨在提供一系列实用的编程技巧,帮助开发者提升效率,写出更高效、...

    lisp.js:一个非常小的 javascript 中的 Lisp 解释器

    除了基本功能外,开发者还可以根据需求扩展`lisp.js`,增加对更多Lisp特性的支持,例如宏系统、惰性求值、尾递归优化等。这样的实践不仅可以深化对Lisp语言的理解,也锻炼了开发者在JavaScript上的编程技巧。 总结...

    Javascript中最常用的55个经典技巧

    JavaScript,作为全球最广泛使用的编程语言之一,拥有丰富的特性与技巧。以下将详细解析JavaScript中最常用的55个经典技巧,帮助你提升编程效率和代码质量。 1. **变量声明**:使用`let`和`const`代替`var`,以避免...

    功能性JS

    功能性JS,也称为函数式JavaScript,是编程范式的一种,它强调使用函数作为构建软件的基本单元,通过组合函数而不是改变状态或操作数据来解决问题。在JavaScript这个动态且广泛使用的脚本语言中,函数式编程提供了更...

    JavaScript程序设计JavaScript运行原理(

    未优化的代码首先会被编译成“快速路径”(也称为“惰性编译”),然后根据执行情况进一步优化为更高效的机器码。 执行上下文是JavaScript中的一个重要概念,它决定了变量、函数和this的查找规则。每当代码被执行时...

    js_war:一些有趣的js问题

    9. **JavaScript引擎优化**:了解V8引擎的惰性编译、优化编译和回退策略,以及如何编写有利于引擎优化的代码,如避免使用with语句和不必要的动态属性访问。 10. **ES6新特性**:包括箭头函数、模板字符串、let和...

    深入理解JavaScript系列(25):设计模式之单例模式详解

    在JavaScript中实现单例模式的一种最直接方式是利用对象字面量: ```javascript var mySingleton = { property1: "something", property2: "somethingelse", method1: function() { console.log('helloworld');...

    vue3面试题,JavaScript面试题

    Vue.js 3.0 带来了许多改进和优化,其中最重要的变化之一是对响应式系统的重新设计。在Vue 2.x中,响应式系统依赖于`Object.defineProperty`来劫持对象属性,但在Vue 3.0中,Vue利用了ES6的`Proxy` API来实现更为...

    iffl

    2. **闭包**:JavaScript支持闭包,允许函数访问并操作其词法作用域内的变量,即使在其定义的作用域之外。这在实现数据封装和模块化时非常有用。 3. **惰性计算**:IFL可能引入惰性计算,这意味着计算仅在需要时...

Global site tag (gtag.js) - Google Analytics