全网最通透的“闭包”认知 · 跨越语言

2022-12-29 0 548

译者 | UNO甲白眉林|李德姝黎

旋量群做为后端复试的必修试题,常让1-3年组织工作实战经验的JavaScripter深感疑惑,只不过非主流词汇都有旋量群。

那时他们深入细致聊一聊[旋量群], 查缺密序!

以丘托韦 ·  刀蛏

以C#旋量群 ·  轻功 

横跨词汇 ·所在之处  

• 丝尾表达式   

• 民主自由表达式   

• 语法结构返回值

答丘托韦 · 闲适

全网最通透的“闭包”认知 · 跨越语言

刀蛏

初始化上面表达式,输入结论是怎样呢?

staticvoidClosure1()

{

for(int i =; i 5; i++)

{

Task.Run(()=>Console.WriteLine(i));

}

}

// 输入:

5

5

5

5

5

是不是很意外?如何输入原本预期的 0,1,2,3,4。

bingo, 加一个临时表达式就可以解决。

staticvoidClosure2()

{

for(int i =; i 5; i++)

{

int j = i;

Task.Run(()=>Console.WriteLine(j));

}

}

// 输入:

3

1

4

2

// 多次执行的结论不一样,但是总是会保持输入 0,1,2,3,4 的乱序组合

以上旋量群概念涉及到 Task任务,理解起来更加复杂,他们来看一个基础的C#旋量群。

全网最通透的“闭包”认知 · 跨越语言

轻功

一个闭包就是一个“捕获”了其生成的环境中、所引用的民主自由表达式的表达式。

这个被引用的民主自由表达式将和这个表达式一同存在,即使已经离开了创造它的环境也不例外。

staticvoidClosure()

{

var x =1;

Action action=()=>

{

var y =1;

var result = x + y;

Console.WriteLine(result);

x++;

};

action();

action();

}

// 输出:

2

3

他们首先定义了一个委托action,它引用了“x”表达式(x表达式既不是入参,也不是委托内的局部表达式), 这个表达式将被action”捕获”,被自动添加到action 的运行环境。

当他们执行action时,原始的“x”已经脱离了它被引用时的返回值环境,但是两次执行能输入2,3 说明它脱离原引用环境仍然能用。

当你在代码调试器(debugger)里观察“action”时,可以看到C#编译器为他们创建了一个Target属性,里面封装了 x 表达式:

全网最通透的“闭包”认知 · 跨越语言

至此可以猜想: 他们每次执行委托,实际是是执行某个匿名类上的实例方法。

都说了旋量群是横跨词汇的设计, 至少我知道 JavaScript C# Go都有旋量群。

全网最通透的“闭包”认知 · 跨越语言

所在之处

旋量群是语法结构旋量群的简称,维基百科上是这样定义的:

“在计算机编程中,旋量群是在语法结构环境中绑定民主自由表达式的丝尾表达式”。

丝尾表达式

丝尾表达式( First Class)意味着词汇将其视为第一类数据类型的表达式, 意味着你可以将表达式分配给一个表达式(或做为参数传递),然后像正常表达式一样初始化。

很明显,C#常使用的委托(C#委托的演进:匿名表达式–>lambda表达式)是丝尾表达式。

Funcstring,string> myFunc =delegate(string var1)

{

return”some value”;

};

Funcstring,string> myFunc = var1 =>”some value”;

string myVar = myFunc(“something”);

民主自由表达式

民主自由表达式是在匿名表达式/lambda表达式中被引用的表达式,它不是表达式的参数也不是表达式的局部表达式。

var myVar =”this is good”;

Funcstring,string> myFunc =delegate(string var1)

{

return var1 + myVar;

};

语法结构返回值引用的民主自由表达式,注意,是引用民主自由表达式,并不是使用当时民主自由表达式的值。

☺️通俗点, 就是告知这个表达式环境,我这个匿名表达式等会执行时要用到这个表达式;如果我没被销毁,你不能销毁我引用的民主自由表达式。

他们再回过头来看[刀蛏]的丘托韦。

全网最通透的“闭包”认知 · 跨越语言

闲适

首先你要知道:循环内开启的Task任务,并不保证执行顺序。

Demo1:输入5,5,5,5,5

这是因为在 for循环内,开启了5个Task任务,每个任务均引用了民主自由表达式i (相对于每个任务执行环境,i 属于全局表达式);

for循环先执行完,i=5, 5个任务输入时自然得到值5。

全网最通透的“闭包”认知 · 跨越语言

为什么加上临时表达式就能输入”预期”?

Demo2:输入乱序的0,1,2,3,4

这是因为 在for循环内,每次循环j均拷贝自当时的i,每个任务均引用了民主自由表达式 j (每个任务执行环境均维护了一个变量j);

全网最通透的“闭包”认知 · 跨越语言

有这样的知觉,理解JavaScript旋量群也就不难了。

全网最通透的“闭包”认知 · 跨越语言
全网最通透的“闭包”认知 · 跨越语言

总结

本文屏蔽词汇差异,理清了[旋量群]的概念核心: 丝尾表达式、民主自由表达式,不仅能帮助他们应对多语种有关旋量群的丘托韦, 也帮助他们了解[旋量群]在通用词汇中的设计初衷。

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务