【Dart学习】-- Dart之匿名方法&闭包

一,匿名方法定义

(参数1,参数2,....){

    方法体...
     return 返回值
 }

二,匿名方法特性

  • 可赋值给变量,通过变量进行调用
  • 可在其他方法中直接调用或传递给其他方法

    
    

    void main(List<String> args) {
     //无参匿名函数
     var func = () {
       print("Hello");
      };
     func();

    //有参匿名函数
     var func1 = (str) {
       print("Hello-------$str");
     };
     func1("huangxiaoguo");

    
    

    //通过()进行调用,不推荐使用
      (() {
        print("通过()进行调用,不推荐使用");
      })();

    
    

    //匿名方法传参
      var list2 = [‘h‘, ‘e‘, ‘l‘, ‘l‘, ‘o‘];
      print(listTimes(list2, (str) {
        return str * 3;
      }));
    }

    
    

    List listTimes(List list, String times(str)) {
       for (var i = 0; i < list.length; i++) {
        list[i] = times(list[i]);
       }
       return list;
     }

    打印结果:

    Hello
    Hello-------huangxiaoguo
    通过()进行调用,不推荐使用
    [hhh, eee, lll, lll, ooo]
    Exited

三,什么是闭包?闭包的优缺点?

  • 1、变量作用域

    要理解闭包,首先要理解Dart的特殊的变量作用域。

    变量的作用域无非就两种:全局变量和局部变量。

    Dart语言的特别之处就在于:函数内部可以直接读取全局变量,但是在函数外部无法读取函数内部的局部变量。

  • 2、如何从外部读取函数内部的局部变量?


    (1)出于种种原因,我们有时候需要获取到函数内部的局部变量。但是,上面已经说过了,正常情况下,这是办不到的!只有通过变通的方法才能实现。

    那就是在函数内部,再定义一个函数。

    a() {
      int count = 0;
      printCount() {
        print(count++);
      }
      return printCount;
    }
    
    b() {
      int count = 10;
      return () {
        print(--count);
      };
    }

    (2)在上面的代码中,函数printCount就被包括在函数a内部,这时a内部的所有局部变量,对printCount都是可见的。但是反过来就不行,printCount内部的局部变量,对a就是不可见的。

    这就是Dart语言特有的"链式作用域"结构(chain scope),

    (3)子对象会一级一级地向上寻找所有父对象的变量。所以,父对象的所有变量,对子对象都是可见的,反之则不成立。

    既然printCount可以读取a中的局部变量,那么只要把printCount作为返回值,我们不就可以在a外部读取它的内部变量了吗!

    void main(List<String> args) {
      var func = a();
      for (var i = 0; i < 5; i++) {
        func();
      }
      print("-------------------------");
      var func1 = b();
      for (var i = 0; i < 5; i++) {
        func1();
      }
    }
    
    a() {
      int count = 0;
      printCount() {
        print(count++);
      }
      return printCount;
    }
    
    b() {
      int count = 10;
      return () {
        print(--count);
      };
    }
  • 3、闭包的概念


    上面代码中的a中的 printCount函数 和 b中匿名函数,就是闭包

    各种专业文献的闭包定义都非常抽象,我的理解是: 闭包就是能够读取其他函数内部变量的函数

    由于在Dart中,只有函数内部的子函数才能读取局部变量,所以说,闭包可以简单理解成“定义在一个函数内部的函数“。

    所以,在本质上,闭包是将函数内部和函数外部连接起来的桥梁

  •  4、闭包的用途

    闭包可以用在许多地方。它的最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中,不会在a()b()调用后被自动清除。

    为什么会这样呢?原因就在于aprintCount的父函数,而printCount被赋给了一个全局变量,这导致printCount始终在内存中,而printCount的存在依赖于a,因此a也始终在内存中,不会在调用结束后,被垃圾回收机制(garbage collection)回收。

  • 5、使用闭包的注意点

    (1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。

    (2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。

原文地址:https://www.cnblogs.com/lxlx1798/p/11038986.html

时间: 2024-08-01 13:06:12

【Dart学习】-- Dart之匿名方法&闭包的相关文章

【dart学习】-- Dart之函数

1. 指定返回值得函数 /** * 无返回值的函数 * params: 可以是任意类型(var和Object类型也可以任意类型). 当然这里的参数类型你可以随意指定我这里已dynamic为例 * 参数类型:你也可以指定var.Object等,再比如说你可以指定num, int,double, String.... * 如果我们对参数没有限制的话可以使用这个 */ void printDynamicParams(dynamic params){ print(params); } 主函数中我们调用p

委托学习笔记后续:泛型委托及委托中所涉及到匿名方法、Lambda表达式

引言: 最初学习c#时,感觉委托.事件这块很难,其中在学习的过程中还写了一篇学习笔记:委托.事件学习笔记.今天重新温故委托.事件,并且把最近学习到和委托相关的匿名方法.Lambda表达式及泛型委托记录下来,以备复习使用. 委托: 日常工作中,常常见到委托用在具体的项目中.而且委托使用起来相对来说也是非常简单的,下面列举一个委托实例用以说明如何使用委托,代码如下: class Program { public delegate int CalculateDelegate(int x, int y)

C#封装、多态、抽象、接口、匿名方法等学习

1:封装 将对象进行封装,并不等于将整个对象完全包裹起来,而是根据实际需要,设置一定的访问权限,用户根据不同的权限调用对象提供的功能,在C#语言中,可以使用修饰符public.internal.protected.private分别修饰类的字段.属性和方法. 2:继承,主要是注意继承的格式 [csharp] view plaincopy public class ParentClass  //父类 { public ParentClass(); } public class ChildClass

C#学习:委托、事件、匿名方法

一.委托: 委托给我的感觉就是一个种类型,可以让方法更具面向对象的特性——你看,其实我也没说明白,因为我也不大理解.还是一步步往下学吧. 具体来说,委托就是一个类似下面的这种东西: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Collections; namespace ConsoleTestCsharp { class Program { d

C#学习笔记(六):可空类型、匿名方法和迭代器

可空类型 为啥要引入可空类型? 在数据库中,字段是可以为null值的,那么在C#中为了方便的操作数据库的值,微软引入了可空类型. 声明可空类型 我们可以使用两种方法声明一个可空类型: 1 Nullable<int> i = null; 2 int? i = null; 第二行是第一行的简写方法,其中“?”是微软为可空类型提供的一个语法糖. 我们看看可空类型的实现: 1 // Type: System.Nullable`1 2 // Assembly: mscorlib, Version=4.0

【dart学习】-- Dart之基础语法

一,重要概念 所有你能够赋值给一个变量的都是一个对象,无论是变量,数字,函数等都是一个对象.所有的对象都是类的一个实例.所有的对象都继承自内置的Object类.这一点类似于Java语言“一切皆对象”. 虽然Dart是强类型语言,但是类型声明是可选项(即不是必须的),因为Dart可以自己去推断类型.这点与JS和Swift很类似.比如var number = 1,变量number就被推断为int类型.当你想明确说没有类型时,可以使用特殊类dynamic/object声明(详情下面会讲到). Dart

C#学习笔记三: C#2.0泛型 可控类型 匿名方法和迭代器

前言 C#1.0的委托特性使方法作为其他方法的参数来传递,而C#2.0 中提出的泛型特性则使类型可以被参数化,从而不必再为不同的类型提供特殊版本的实现方法.另外C#2.0还提出了可空类型,匿名方法和迭代器3个优美的特性. 1,泛型1.1 泛型是什么泛型的英文表述是"generic", 这个单词意为通用的.从字面意思可知,泛型代表的就是"通用类型",它可以代替任意的数据类型,使类型参数化,从而达到之实现一个方法就可以操作多种数据类型的目的.泛型是将方法实现行为与方法操

JavaScript学习总结(十六)——Javascript闭包(Closure)

原文地址: http://www.cnblogs.com/xdp-gacl/p/3703876.html 闭包(closure)是Javascript语言的一个难点,也是它的特色, 很多高级应用都要依靠闭包实现.很早就接触过闭包这个概念了,但是一直糊里糊涂的,没有能够弄明白JavaScript的闭包到底是什么,有什么用,今天 在网上看到了一篇讲JavaScript闭包的文章(原文链接), 讲得非常好,这下算是彻底明白了JavaScript的闭包到底是个神马东东以及闭包的用途了,在此写出来和大家分

C#学习日记25---匿名方法 与 Func委托 与 lambda表达式

       在 2.0 之前的 C# 版本中,声明委托的唯一方法是使用命名方法.C# 2.0 引入了匿名方法(委托),而在 C# 3.0 及更高版本中,Lambda 表达式取代了匿名方法,作为编写内联代码的首选方式. 匿名委托(方法): 匿名委托的叫法并不准确,准确的应该叫做匿名方法,(总之两者是一个意思啦).前面  委托类型  中我已经提到过,委托是用于引用与其具有相同标签的方法.换句话说,您可以使用委托对象调用可由委托引用的方法(参数是方法名).而匿名方法则是将代码块作为委托参数(参数是实