Dart 函数

1、函数声明
(1)、直接声明
       Dart 中声明函数不需要使用 function 关键字
(2)、箭头函数
       Dart 中的箭头函数,函数体只能写一行且不能带有结束的分号
       Dart 中的箭头函数,只是函数的一种简写形式
(3)、匿名函数
(4)、立即执行函数
  // 直接声明
  void printMsg() {
    print('Hello Dart');
  }

  // 返回值与函数声明的类型要保持一致
  String getNum(int num) {
    return 'Age $num';
  }

  // 调用函数
  printMsg(); // Hello Dart
  print(getNum(18)); // Age 18

  List fruits = ['apple', 'banana', 'cherry'];
  // 匿名函数
  final myPrint = (value) {
    print(value);
  };
  fruits.forEach(myPrint);

  // 箭头函数
  fruits.forEach((element) => {
        // print(element); // 错误:Expected to find '}'
        print(element)
      });
  fruits.forEach((element) => print(element));

  // 立即执行函数
  ((int n) {
    print(n);
  })(5); // 5
  ((int n) {
    print(n);
  }(55)); // 55
 
2、函数参数
(1)、必填参数
       参数类型 参数名称 如:int age
(2)、可选参数
       放在必填参数后面
       通过 中括号 包起来
       带默认值的可选参数
(3)、命名参数
       用 大括号 包起来
       调用函数时,命名参数的名称与声明函数中的名称保持一致
  // 必填参数
  int getAge(int age) {
    return age;
  }

  // 可选参数
  // The parameter 'age' can't have a value of 'null' because of its type,
  // but the implicit default value is 'null'.
  // 错误:指定了可选参数age是int类型,但是,如果不传age,该值会是null
  String getUserInfo(String username, [int age]) {
    return '姓名:$username,年龄:$age';
  }

  // 解决方法1:把可选参数的数据类型指定为 dynamic
  String getUserInfo(String username, [dynamic age]) {
    return '姓名:$username,年龄:$age';
  }

  // 解决方法2:给可选参数赋一个默认值
  String getUserInfo(String username, [int age = 1]) {
    return '姓名:$username,年龄:$age';
  }

  String bob = getUserInfo('bob', 23);
  String jim = getUserInfo('jim');
  print(bob); // 姓名:bob,年龄:23
  print(jim); // 姓名:jim,年龄:1

  // 命名参数
  String getScore(String subject, {double score = 0}) {
    return '科目:$subject,分数:$score';
  }

  String math = getScore('数学', score: 123);
  print(math); // 科目:数学,分数:123.0

 

3、Dart 函数 - 作用域

Dart 函数的作用域和JS基本一致,也分为全局作用域和函数作用域。
内层函数可以访问外层函数的变量,逐层向上直至全局作用域,形成一个作用域链。相反,外层函数不能直接访问内层函数中的变量
// 全局变量
var globalNum = 20;

void main() {
  printInfo() {
    // 局部变量
    var localNum = 10;
    print(localNum); // 10
    print(globalNum); // 20 可以在函数作用域中,访问全局变量
  }

  printInfo();
  // 不可以在全局作用域中,访问局部变量
  print(localNum); // Error: Undefined name 'localNum'
}

 

4、Dart 函数 - 闭包


Dart中闭包的实现方式与JS完全一致

使用时机:既要重用变量,又要保护变量不被污染

实现原理:外层函数被调用后,外层函数的作用域对象(AO)被内层函数引用着,导致外层函数的作用域对象无法释放,从而形成闭包
void main() {
  printInfo() {
    // 局部变量
    var localNum = 10;

    print(localNum);
    localNum--;
  }

  // 预期:每调一次printInfo函数,localNum的数值就会相应减1
  // 实际:当函数执行完毕后,全局执行上下文栈会弹出该函数执行上下文,定义在上面的所有变量和函数都会被销毁
  printInfo(); // 10
  printInfo(); // 10
  printInfo(); // 10

  // 改造:outer函数返回了一个引用该函数作用域下变量的函数,由于局部变量被引用着,所以不会销毁执行上下文,由此形成了一个闭包
  outer() {
    var localNum = 10;
    return () {
      print(localNum);
      localNum--;
    };
  }

  var p = outer();
  p(); // 10
  p(); // 9
  p(); // 8
}

 

5、Dart 函数 - 异步函数

JS中,异步调用可以通过 Promise 来实现
  async函数返回一个Promise,await用于等待Promise

Dart中,异步调用通过 Future 来实现
  async函数返回一个Future,await用于等待Future
/*
http是一个外部的模块,直接引用会报如下错误:
Error: Couldn't resolve the package 'http' in 'package:http/http.dart'.

解决步骤如下:
1、打开 https://pub.dev/
2、在根目录下新建一个 pubspec.yaml 文件,并添加如下内容
name: dart

environment:
  sdk: ">=2.7.0 <3.0.0"

dependencies:
  http: ^0.13.4
3、保存后会自动安装依赖并生成.packages, pubspec.lock, .dart_tool 三个文件/夹
 */
import 'package:http/http.dart' as http;
import 'dart:convert' as convert;

Future getDog() {
  final url = Uri.http('dog.ceo', '/api/breeds/image/random/3');
  return http.get(url).then((resp) {
    // print(resp); // Instance of 'Response'
    // print(resp.body);
    // {"message":["https:\/\/images.dog.ceo\/breeds\/beagle\/n02088364_5716.jpg","https:\/\/images.dog.ceo\/breeds\/terrier-irish\/n02093991_3935.jpg",
    // "https:\/\/images.dog.ceo\/breeds\/clumber\/n02101556_7923.jpg"],"status":"success"}
    var jsonResponse = convert.jsonDecode(resp.body) as Map<String, dynamic>;
    print(jsonResponse);
    return jsonResponse;
  });
}

void main() {
  getDog().then((res) => print(res)).catchError((error) => print(error));
}
import 'package:http/http.dart' as http;
import 'dart:convert' as convert;

Future getDog() async {
  final url = Uri.http('dog.ceo', '/api/breeds/image/random/3');
  final response = await http.get(url);
  Map resultMap = convert.jsonDecode(response.body) as Map<String, dynamic>;
  return resultMap;
}

void main() async {
  try {
    final result = await getDog();
    if (result['status'] == 'success') {
      print(result);
    }
  } catch (e) {
    print(e);
  }
}

 

posted @ 2022-04-21 14:24  rogerwu  阅读(287)  评论(0编辑  收藏  举报