闭包的简单定义和使用

<span style="font-size:18px;">    /* 闭包(Closures)
     * 闭包是自包含的功能代码块,可以在代码中使用或者用来作为参数传值。
     * 在Swift中的闭包与C、OC中的blocks和其它编程语言(如Python)中的lambdas类似。
     * 闭包可以捕获和存储上下文中定义的的任何常量和变量的引用。这就是所谓的变量和变量的自封闭,
     * 因此命名为”闭包“("Closures)").Swift还会处理所有捕获的引用的内存管理。
     *
     * 全局函数和嵌套函数其实就是特殊的闭包。
     * 闭包的形式有:
     * (1)全局函数都是闭包,有名字但不能捕获任何值。
     * (2)嵌套函数都是闭包,且有名字,也能捕获封闭函数内的值。
     * (3)闭包表达式都是无名闭包,使用轻量级语法,可以根据上下文环境捕获值。
     *
     * Swift中的闭包有很多优化的地方:
     * (1)根据上下文推断参数和返回值类型
     * (2)从单行表达式闭包中隐式返回(也就是闭包体只有一行代码,可以省略return)
     * (3)可以使用简化参数名,如$0, $1(从0开始,表示第i个参数...)
     * (4)提供了尾随闭包语法(Trailing closure syntax)
     */  

     // 下面用Swift标准库中的sort方法来一步步简化闭包写法
     // sort函数需要两个参数
     // 参数一:数组
     // 参数二:一个闭包:带有两个参数,这两个参数类型与数组中的元素类型相同,返回值是Bool
<span style="color:#009900;">     var names = ["Swift", "Arial", "Soga", "Donary"]  </span>

     // 第一种方式:使用函数
<span style="color:#009900;">     func backwards(firstString: String, secondString: String) -> Bool {
       return firstString > secondString // 升序排序
     }  </span>
     // 这里第二个参数,传了一个函数
<span style="color:#009900;">     // reversed is equal to ["Swift", "Soga", "Donary", "Arial"]
     var reversed = sort(nams, backwards)  </span>

     // 第二种方式:使用闭包方式
     // 完整闭包写法是在花括号内有参数列表和返回值,用关键字in表明闭包体的开始
     // (firstString: String, secondString: String) 闭包参数列表
     // -> Bool 指明闭包返回值类型是Bool
     // <span style="background-color: rgb(255, 255, 0);">in关键字表明闭包体的开始 </span>
<span style="color:#009900;">     reversed = sort(names, { (firstString: String, secondString: String) -> Bool in
        return firstString > secondString
        })  </span>

     // 这里可以进一步简化写法,因为闭包代码比较短,可以写到一行上
<span style="color:#009900;">     reversed = sort(names, { (firstString: String, secondString: String) -> Bool in
return firstString > secondString})  </span>

    // 下面再进一步简化写法 :根据环境上下文自动推断出类型
    // 参数列表都没有指明类型,也没有指明返回值类型,这是因为swift可以根据上下文推测出
    // firstString和secondString的类型会是names数组元素的类型,而返回值类型会根据return语句结果
得到
    <span style="color:#009900;">reversed = sort(names, { firstString, secondString in return firstString >
secondString})  </span>

    // 再进一步简化:隐式返回(单行语句闭包)
    // 因为闭包体只有一行代码,可以省略return
    <span style="color:#009900;">reversed = sort(names, { firstString, secondString in firstString > secondString})</span>  

    // 再进一步简化:使用简化参数名($i,i=0,1,2...从0开始的)
    // Swift会推断出闭包需要两个参数,类型与names数组元素相同
<span style="color:#009900;">    reversed = sort(names, { $0 > $1 })   </span> 

    // 最简单的一种写法:使用操作符
<span style="color:#009900;">    reversed = sort(names, >)     </span> 

    /*
     * 尾随闭包(Trailing Closures)
     * 如果函数需要一个闭包参数作为参数,且这个参数是最后一个参数,而这个闭包表达式又很长时,
     * 使用尾随闭包是很有用的。尾随闭包可以放在函数参数列表外,也就是括号外。如果函数只有一个参数,
     * 那么可以把括号()省略掉,后面直接跟着闭包。
     */
    // Array的方法map()就需要一个闭包作为参数
<span style="color:#009900;">    let strings = numbers.map { // map函数后面的()可以省略掉
      (var number) -> String in
      var output = ""
      while number > 0 {
        output = String(number % 10) + output
        number /= 10
      }
      return output
    }  </span>

    /* 捕获值
     * 闭包可以根据环境上下文捕获到定义的常量和变量。闭包可以引用和修改这些捕获到的常量和变量,
     * 就算在原来的范围内定义为常量或者变量已经不再存在(很牛逼)。
     * 在Swift中闭包的最简单形式是嵌套函数。
     */
<span style="color:#009900;">    func increment(#amount: Int) -> (() -> Int) {
      var total = 0
      func incrementAmount() -> Int {
        total += amount // total是外部函数体内的变量,这里是可以捕获到的
        return total
      }
      return incrementAmount // 返回的是一个嵌套函数(闭包)
    }   </span>  

    // 闭包是引用类型,所以incrementByTen声明为常量也可以修改total
<span style="color:#009900;">    let incrementByTen = increment(amount: 10)
    incrementByTen() // return 10,incrementByTen是一个闭包  </span>
    // 这里是没有改变对increment的引用,所以会保存之前的值
 <span style="color:#009900;">   incrementByTen() // return 20
    incrementByTen() // return 30     

    let incrementByOne = increment(amount: 1)
    incrementByOne() // return 1
    incrementByOne() // return 2
    incrementByTen() // return 40
    incrementByOne() // return 3  </span></span>
时间: 2024-10-25 04:11:09

闭包的简单定义和使用的相关文章

Swift学习--闭包的简单使用(三)

一.Swift中闭包的简单使用 override func viewDidLoad() { super.viewDidLoad() /** 闭包和OC中的Block非常相似 OC中的block类似于匿名函数 闭包是用来定义函数 作用:Block是用于保存一段点,在需要的时候执行 闭包也是用于保存一段点,在需要的时候执行做一个耗时操作 */ /** 闭包的基本格式: { (形参列表)->() in 需要执行的代码 } */ /** * 闭包的几种格式: 1.将闭包通过实参传递给函数 2.如果闭包是

经典面试题,循环中使用闭包解决 var 定义函数的问题--闭包

闭包的定义很简单:函数 A 返回了一个函数 B,并且函数 B 中使用了函数 A 的变量,函数 B 就被称为闭包. <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>var定义函数出现的问题</title></head><body><script type="text/ja

闭包的简单实例和解释

var fff=(function(){ var a=1; function fn1(){ a++; console.log(a); }; function fn2(){ return a+10; }; return {f1:fn1, f2:fn2};})() var ss=fff.f1; var cc=console.log(fff.f2());//11 ss();//2 var fnbg=function(num){ var number=num; return function bg(nu

对闭包的简单理解

javascript理解js闭包 闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量. Js代码 var n=999; function f1(){ alert(n); } f1(); // 999 另一方面,在函数外部自然无法读取函数内的局部

闭包的简单理解

什么是闭包? 简单来说,闭包是指可以访问另一个函数作用域变量的函数,一般是定义在外层函数中的内层函数. (父函数包裹子函数,这个子函数中存在能够访问父函数中变量的引用,这个子函数就是闭包) 为什么需要闭包? 局部变量无法共享和长久的保存,而全局变量可能造成变量污染,所以我们希望有一种机制既可以长久的保存变量又不会造成全局污染,在全局作用域中可以访问到被保存在局部作用域的变量. 特点 占用更多内存 不容易被释放 何时使用? 变量既想反复使用,又想避免全局污染 如何使用? 1.定义外层函数,封装被保

javascript类的简单定义

在面向对象编程中,类(class)是对象(object)的模板,定义了同一组对象(又称"实例")共有的属性和方法. Javascript语言不支持"类",但是可以用一些变通的方法,模拟出"类". 一.构造函数法 这是经典方法,也是教科书必教的方法.它用构造函数模拟"类",在其内部用this关键字指代实例对象. function Cat() { this.name = "大毛"; } 生成实例的时候,使用ne

对闭包的简单了解

什么是闭包?通俗的说闭包是指能读取其他函数内部的函数.这句话又是什么意思呢?我们来看个例子 function a(){ var i=0; function b(){ alert(++i); } return b; } var c=a(); c(); 这段代码定义了一个函数a,在函数a的内部嵌套了另一个函数b,而这个函数a又返回函数b,在函数a的外部我们定义了一个变量c,这个变量c表面上指向的是函数a,但是根据函数a的结构可看出变量c实际上指向的是函数b. 这段代码其实就创建了一个闭包,为什么?因

JSON语法-对对象的简单定义

 JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.它基于ECMAScript的一个子集. JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C.C++.C#.Java.JavaScript.Perl.Python等).这些特性使JSON成为理想的数据交换语言. 易于阅读和编写,同时也易于机器解析和生成(网络传输速). 上面是官方定义,我看不懂.我只是对json的由来比较感兴趣. 言归正传,json语法规则: 数据在键

javascript中闭包最简单的简绍

javascript中闭包是什么 JavaScript 变量可以是局部变量或全局变量.私有变量可以用到闭包.闭包就是将函数内部和函数外部连接起来的一座桥梁. 函数的闭包使用场景:比如我们想要一个函数来执行计数功能. 如果设计全局变量 1 var counter=0; 2 function add(){ 3 4 return counter++;} // add(); 在浏览器调用 add();//值为2 问题是如何当我们设计另外一个方法时用到需要counter这个变量,我们在进行修改无疑会改变c