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); } }