美文网首页
2.2、Dart语言基础:函数与闭包

2.2、Dart语言基础:函数与闭包

作者: 双鱼子曰1987 | 来源:发表于2021-12-14 10:54 被阅读0次

    学习笔记,旨在于快速入门和学习Dart,其中可能会有理解错误,请指出,一起学习。

    系列文章

    2.1、Dart语言基础:变量、运算符
    2.2、Dart语言基础:函数与闭包
    2.3、Dart语言基础:面向对象
    2.4、Dart语言基础:异步
    2.5、Dart语言基础:库与包
    ...

    一、概述

    • Dart中函数是一等公民,因此,其可当做函数参数,可复制给变量;

    • 函数声明(与C语言类似)

    void sayHello(String name) {
      print('$name say hello!');
    }
    
    // Tom say hello!
    sayHello('Tom'); 
    

    虽然可以省略参数类型和返回值类型,但是推荐最好写明白。

    • 箭头函数
      当函数只有一条语句, 可以使用 箭头函数=> expr 进行简写。
    void sayHello(String name) => print('$name say hello!');
    
    // Tom say hello!
    sayHello('Tom'); 
    
    • 返回值:如果没有显示返回,则默认返回null
      All functions return a value. If no return value is specified, the statement return null;

    二、函数参数

    • 参数的类型分为两种: 位置参数(positional parameters)命名参数(named parameters)

    1、命名参数

    语法格式:{param1, param2, …},如下
    void introduce_1({String? name, int? age}) {
      print("$name and $age");
    }
    
    // 1、null and null
    introduce_1();
    // 2、null and 30
    introduce_1(age: 30);
    // 3、tom and 30
    introduce_1(name: 'tom', age: 30);
    
    • 调用函数时,可选参数可以不传递,其默认为null
    • 命名参数,调用函数时的入参顺序 与定义的参数位置无关。
    void introduce_1_1({String? name='def', int? age}) {
      print("$name and $age");
    }
    
    // 1、def and 30
    introduce_1_1(age: 30);
    
    // 2、tom and 30
    introduce_1_1(name: 'tom', age: 30);
    
    • 支持设定 默认参数;函数调用时,默认参数可传递也可不传递。
    void introduce_1_2({required String? name, int? age}) {
      print("$name and $age"); 
    }
    
      // Error: Required named parameter 'name' must be provided.
      introduce_1_2(age: 30);  
      // tom and null
      introduce_1_2(name: 'tom');
    
    • 标记为必须参数,关键字required
    • 函数调用时,required 参数 必须入参,否则编译报错。
    void introduce_10({String name, int age}) {
      print("$name and $age"); 
    }
    
    // 编译器报错:类型不匹配的错误
    Error: The parameter 'name' can't have a value of 'null' because of its type 'String', but the implicit default value is 'null'.
    Error: The parameter 'age' can't have a value of 'null' because of its type 'int', but the implicit default value is 'null'.
    
    • 参数必须为 可选类型(即用?标记);调用方式func(paramName: value);
    语法格式2:{param1: value1, param2: value2, ...},需要指定默认值
    void introduce_2({name: 'err', age: 0}) {
      print("$name and $age");
    }
    
      // 1、err and 0
      introduce_2();
      // 2、err and 30
      introduce_2(age: 30);
      // 3、tom and 30
      introduce_2(name: 'tom', age: 30);
    

    2、位置参数(positional parameters)

    void say_1(String from, String msg) {
      print('$from says $msg');
    }
    
      // 1、tom says hello world!
      say_1('tom', 'hello world!');
      // 2、Error: Too few positional arguments: 2 required, 1 given.
      say1('tom');
    
    • 调用函数时,位置参数 必须传递全部参数,且顺序必须一致,类型也必须一致。
    String say_1_1(String from, String msg, [String? device]) {
      var result = '$from says $msg';
      if (device != null) {
        result = '$result with a $device';
      }
      return result;
    }
    
    // 1、Bob says Howdy
    print(say_1_1('Bob', 'Howdy')); 
    // 2、Bob says Howdy with a smoke signal
    print(say_1_1('Bob', 'Howdy', 'smoke signal'));
    
    • 支持声明 可选的位置参数;语法格式:[可选位置参数列表],如上。
    • 调用时候,可选的位置参数可以不传递。
    String say_1_2(String from, String msg, [String? device = 'iphone']) {
      var result = '$from says $msg';
      if (device != null) {
        result = '$result with a $device';
      }
      return result;
    }
      // 1、Bob says Howdy with a smoke signal
      print(say_1_2('Bob', 'Howdy', 'smoke signal'));
      // 2、Bob says Howdy with a iphone
      print(say_1_2('Bob', 'Howdy'));
    
    • 可选位置参数,支持默认参数。如上

    3、默认参数值

    • 位置参数 和 命名参数 都支持设置函数的默认值;语法格式:param = value ,具体如上。
    • 默认值只能是编译时常量, 如果没有提供默认值,则默认值为 null。
      The default values must be compile-time constants. If no default value is provided, the default value is null.

    4、一个函数可以同时定义 命名参数位置参数

    void sayHelloworld_1(String name, {int? age}) {
      print("$name say hello,and age is $age!");
    }
    // 1、tom say hello,and age is null!
    sayHelloworld_1('tom');
      
    // 2、tom say hello,and age is 30!
    sayHelloworld_1('tom', age: 30);
    
    • 调用函数时,可选的命名参数,可以不传递。

    三、匿名函数,Anonymous functions

    • 其他语言,被称为lambda 或 闭包closure。
    • 语法格式:
    ([[Type] param1[, …]]) { 
      codeBlock; 
    }; 
    
    const list = ['apples', 'bananas', 'oranges'];
    list.forEach((item) {
      print('${list.indexOf(item)}: $item');
    });
    
    // 输出如下:
    0: apples
    1: bananas
    2: oranges
    
    • 上面以数组的forEach遍历方法为例:
    list.forEach(
        (item) => print('${list.indexOf(item)}: $item'));
    
    • 单一语句,可以是会用箭头函数

    四、作用域(词法)

    1、词法作用域 Lexical scope

    bool topLevel = true;
    
    void main() {
      var insideMain = true;
    
      void myFunction() {
        var insideFunction = true;
    
        void nestedFunction() {
          var insideNestedFunction = true;
    
          assert(topLevel);
          assert(insideMain);
          assert(insideFunction);
          assert(insideNestedFunction);
        }
      }
    }
    
    • Dart 是一门词法作用域的编程语言,就意味着变量的作用域是固定的。
      Dart is a lexically scoped language, which means that the scope of variables is determined statically, simply by the layout of the code.

    • 可简单的从代码层次结构上看出来,即变量的作用范围,仅局限在其 花括号{} 内。
      You can “follow the curly braces outwards” to see if a variable is in scope.

    2、词法闭包 Lexical closures

    • 闭包本质是一个函数对象,因此其可以 捕获变量 到 闭包的作用域内;即使函数在其原来作用域内使用。
      A closure is a function object that has access to variables in its lexical scope, even when the function is used outside of its original scope.

    • 函数可以 捕获 在其作用域范围内定义的变量。
      Functions can close over variables defined in surrounding scopes.

    • makeAdder() 捕获了 变量addBy 到闭包的作用域内。
      In the following example, makeAdder() captures the variable addBy. Wherever the returned function goes, it remembers addBy.

    Function makeAdder(int addBy, String name) {
      return (int i) => '${addBy + i} $name';
    }
    
      var add2 = makeAdder(2, 'aaa');
      var add4 = makeAdder(4, 'bbb');
      print(add2(3)); // 5 aaa
      print(add4(3)); // 7 bbb
    

    相关文章

      网友评论

          本文标题:2.2、Dart语言基础:函数与闭包

          本文链接:https://www.haomeiwen.com/subject/iusjnltx.html