Open kingcos opened 6 years ago
用JavaScript多了,看Swift的Closure看得费解地吃力,因为JavaScript里也有一个叫Closure的东西,两者虽叫同样的名字,却太不一样。
我来借地盘稍稍比较一下:
Swift中闭包就是一段可以以后call的代码,和其它语言里的匿名函数很像,然后@ escaping和@ nonescaping就是指明一个传进来的闭包是在调用函数返回后还是返回前执行。如果是返回后才会调用的话,调用函数的变量什么的不能被清了。
JavaScript的闭包的话就是一个function和它的所谓lexical environment。
差别不要太大 🤷♂️
@gnijuohz 感谢您的评论~
您说的很对~两门语言的一些语法确实有些类似,但 JS 作为脚本语言,灵活性非常强,又是弱类型,而 Swift 作为强调类型安全的编译语言,确实差别很大。
@kingcos 恩,我再读了下苹果的Closure文档,发现我之前的理解还是有误,苹果的文档这么说的,
Closures can capture and store references to any constants and variables from the context in which they are defined.
然后,
Global and nested functions, as introduced in Functions, are actually special cases of closures. Closures take one of three forms:
Global functions are closures that have a name and do not capture any values.
Nested functions are closures that have a name and can capture values from their enclosing function.
Closure expressions are unnamed closures written in a lightweight syntax that can capture values from their surrounding context.
这样看来,其实两者几乎就是一样的。
@gnijuohz 嗯嗯,不过其实我个人确实一直没有怎么去深入或者比较多得使用过 JS 这门语言😂。
@kingcos 我也是工作之后才深入研究js的哈哈。借你地方总结不好意思了 😅
@gnijuohz 没事儿~欢迎交流哈😀
What
闭包(Closure)在 Swift 等许多语言中普遍存在。熟悉 Objective-C 的同学一定对 Block 不陌生。两者其实是比较类似的,相较于 Block,闭包的写法简化了许多,也十分灵活。
在 Swift 中,
@
开头通常代表着属性(Attribute)。@autoclosure
属于类型属性(Type Attribute),意味着其可以对类型(Type)作出一些限定。How
自动(Auto-)
@autoclosure
名称中即明确了这是一种「自动」闭包,即可以让返回该参数类型的闭包作为参数;error: argument type of @autoclosure parameter must be '()'
。延迟调用(Delay Evaluation)
@autoclosure
独有,但通常搭配使用。@escaping
@escaping
,可以用于处理一些耗时操作的回调;@autoclosure
与@escaping
是可以兼容的,放置顺序可以颠倒。Source Code
Test Cases
inout
与@autoclosure
不兼容,且没有实际意义;@autoclosure
不适用于函数的可变参数(Variadic Parameters)。Use Cases
短路(Short Circuit)运算符
&&
、||
以及??
属于短路运算符,即当表达式左边的结果已经可以决定整个运算符的返回值时(运算符的本质也是函数),右边便没有必要运算。利用了@autoclosure
使得运算符右边可以为闭包,再凭借 Delay Evaluation 特性保证了「短路」。断言(Assert)
@autoclosure
,一是可以直接将闭包直接作为参数;二是当 Release 模式时,Closure 没有必要执行,即可节省开销(XCTest 和 Dispatch 中的部分方法同理)。Summary
@autoclosure
的函数,如果确有必要,也需要做到明确、清晰。Extension
COMPILER_INTRINSIC
COMPILER_INTRINSIC
代表其为编译器的内置函数。Reference