闭包和函数引用

发布于 2022-09-03 15:14:08 字数 482 浏览 16 评论 0

对函数式编程弄得不是很清楚,所以想请假一下下面这两种方法在实现上各有什么优劣点呢?

// 闭包
function func1() {
  // func1
}
function func2() {
  // func2
}
function doSomething(func) {
  return function() {
    // do something...
    return func
  }
}
var func1 = doSomething(func1);
var func2 = doSomething(func2);
// 函数引用
function doSomething() {
  // do something...
}
function func1() {
  doSomething();
  // func1
}
function func2() {
  doSomething();
  // func2
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

瞄了个咪的 2022-09-10 15:14:08

拿func1()来举例子

你两段代码的共同点是 执行func1()调用即执行了func1()的逻辑,又执行了doSomething的逻辑,
区别在于组织代码的时候在第二段代码里你将 doSomething()函数放在了 func1()里,而第一段
代码

function func1() {
  // func1
  alert(a++);
}
function doSomething(func) {
  return function() {
    // do something...
    var a=10;
    return func
  }
}
var funca = doSomething(func1);

func1相当与闭包,你可以在func1里面访问doSomething这个函数实现逻辑过程中的所有数据,但是在第二段
代码里显然没有这个功能

墨小沫ゞ 2022-09-10 15:14:08

我说一个具体的闭包应用

假设func1对两个数求和,func2对两个数求积,如下:

function func1(a, b){ return a+b; }
function func2(a, b){ return a*b; }

现在我们需要为这两个函数分别添加一个日志打印的功能:
1、打印函数执行前的时间戳
2、执行函数
3、打印函数执行后的时间戳
4、返回结果

最直观的方法当然是,定义一个log函数:

function log(func, a, b){
    print_timestamp() // 打印执行前时间戳
    r = func(a, b)    // 执行func并返回结果
    print_timestamp() // 打印执行后时间戳
    return r
}

然后将程序中所有调用func1(a, b)func2(a, b)的地方都分别替换为log(func1, a, b)log(func2, a, b)

可是问题来了,万一程序中调用了func1func2的地方很多,那不是得改到手软?
你说可以用正则批量替换,但万一哪天想撤掉日志打印功能,岂不是又得换回来?
因此改函数名的方法行不通

这时,你又想出另一个方法,在func1func2函数体内注入打印时间戳的代码:

function func1(a, b){ 
    print_timestamp() // 打印执行前时间戳
    r = a+b; 
    print_timestamp() // 打印执行后时间戳
    return r 
}
function func2(a, b){
    print_timestamp() // 打印执行前时间戳
    r = a*b; 
    print_timestamp() // 打印执行后时间戳
    return r 
}

可是问题又来了,万一有n个这样的函数,那岂不是要注入n次代码?
而且这样注入代码,可能还需要原函数的代码结构,容易出错

是时候祭出闭包大法一次性解决性解决这个问题了:

function log(func){
    return function(a, b){
        print_timestamp() // 打印执行前时间戳
        r = func(a, b)    // 执行func
        print_timestamp() // 打印执行后时间戳
        return r          // 返回结果
    }
}
    
var func1 = log(func1)
var func2 = log(func2)

问题解决了,不需要改变调用func1func2的地方,也不需要往func1func2里面注入代码,
只需一次性定义log,然后调用log(func1)就可以获得一个经过修饰的func1
假如日后想要把log功能去掉,只需把var funcn = log(funcn)批量注释即可

究其原因,是因为闭包在传递的时候,会携带自身的状态,
调用log(func1)时,会返回一个函数,这个函数携带的状态就是(func <= func1)
调用log(func2)时,会返回一个函数,这个函数携带的状态就是(func <= func2)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文