目录

闭包与棕喉鸫

闭包

JS 中的闭包

不使用闭包

1
2
3
4
5
6
var a = 1;

function counter() {
  a += 1;
  console.log(a);
}

这样的做法,变量a是环境变量,会导致占用内存过高,变量多了以后,维护起来非常耗费心力(全局变量乱飞)。

使用闭包

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
function counter() {
  var a = 1;

  function inner() {
    a++;
    console.log(a);
  }
  return inner;
}
var c = counter();
c();

同样调用c()函数,打印自动累加值,这样的做法,变量a存在函数对象内,用后可以手动清除内存。

闭包的套路:有嵌套函数,返回值是函数,内部函数引用外部作用域的变量参数,创建一个对象函数。

JS 闭包很强大,可以用闭包模拟私有方法。(这点是与 Java 语言不同之处,在 Java 中声明私有方法很简单,在 JS 中就需要通过别的手段去实现。)

Rust 中的闭包

Rust 是公认对内存安全非常严格的语言,函数作用域内,无法访问函数外部变量,想要达到此效果,需要使用闭包。

不使用闭包

1
2
3
4
5
6
7
fn main() {
    let num = 1;
    fn counter() -> u32 {
        num + 1
    }
    println!("{}", counter());
}

can't capture dynamic environment in a fn item编译会报错。

使用闭包

1
2
3
4
5
6
fn main() {
    let num = 1;
    let counter = || num + 1;

    println!("{}", counter());
}

为什么同样都叫闭包,却在两个不同语言里达到的目的却不相同?

https://image.ericzzz.com/2024%2F04%2F23%2Fb748a4db-e61b-4fed-a28c-7e1ae71e86f6.webp

请看下面的小故事👇。

棕喉鸫

费曼小时候与同伴在田野玩,其中一个小伙伴问他:“你看!你知道那是什么鸟吗?”。

费曼说:“我完全不知道那是什么鸟。”,小伙伴说:“这是棕喉鸫,你爸爸什么都没教你。”。

但事实恰恰相反,费曼的爸爸教过他,并对他说:“你知道这是什么鸟吗?这是棕喉鸫,在葡萄牙语里,它叫 xxx,用意大利语,它叫 xxx,用中文叫 xxx,用日语叫 xxx,你可以用你想了解的所有语种,去称呼这只鸟的名称,但当你叫出它的名称后,你其实对这只鸟还是一无所知,你只是知道了不同地方的人如何称呼这种鸟而已,现在,让我们好好看看这只鸟,观察它在做什么。”

https://image.ericzzz.com/2024%2F04%2F23%2F236396c7-a0b9-4cb0-b05a-5777f3a10dfc.webp

The black-throated thrush (Turdus atrogularis) is a passerine bird in the thrush family. It is sometimes regarded as one subspecies of a polytypic species, “dark-throated thrush”, red-throated thrush then being the other subspecies. More recent treatments regard the two as separate species.

以上来自 wiki 百科的解释。

思考

世界上最遥远的距离,是知道但不理解。 当你了解闭包的概念,阅读代码时一眼就能知道哪里用到了闭包,使用时大脑却一片空白。

知道认识离真正理解,灵活运用还有巨大的鸿沟。不仅要掌握概念,还要理解背后的意义。

参考资料

费曼教授采访