Dart是面向对象的语言,函数也是对象(属于Function对象),可以作为参数传递给其它函数,方便做回调处理
例子:
/// 完整函数写法:包括 返回类型 函数名 参数 函数体 返回值
main() {
var max = maxValue(22, 33);
print(‘$max’);
}
// int maxValue(int a, int b) {
// return a >= b ? a : b;
// }
/// 对于只包含一个表达式的函数,可以使用=>语法简写函数
/// 可以省略返回值类型 编译器会自动转换返回值类型
maxValue(int a, int b) => a >= b ? a : b;

1. 可选参数

(1). 命名可选参数

(2). 位置可选参数

(3). 默认参数值
例子:
import ‘package:meta/meta.dart’;
/// 可选参数
main() {
/// @required修饰的命名或位置参数 调用时可以不传递 默认为null
/// @required修饰位置参数 官方不建议这样使用

/// testRequired1(‘小黄’);
/// 最好不要按照上面的写法 @required可选参数 不设定的话也可以传null
testRequired1(‘小王’, age: null);
testRequired1(‘小黄’, age: 18);
///
testRequired2(‘小杨杨’);
testRequired2(‘小杨杨’, 16);
/// 命名参数 传递参数值时必须指定 参数名:参数值 参数传递不需要按照顺序填写
testStyle1(‘小黄’);
testStyle1(‘小李子’, size: 18.3);
testStyle1(‘小德子’, size: 18.3, bold: true);
testStyle1(‘小德子’, bold: false, size: 18.3);
testStyle2(‘小杨杨’);
/// 位置参数 传递参数值时必须按照参数顺序填写 不需要指定参数名
testStyle2(‘小杨杨’, 20.3);
testStyle2(‘小杨杨’, 20.3, false);
///testStyle2(‘小杨杨’, false, 20.3);
/// 默认参数
defParam1(‘小白’);
defParam1(‘小白’, ‘女’, 22);
defParam1(‘小黄’, ‘男’, 18);
defParam2();
}
void testRequired1(String name, {@required int age}) {
print(‘姓名:$name 年龄:$age’);
}
/// @required修饰位置参数 虽然也可以执行,但是官方不建议这样使用
/// 所以使用位置参数最好不要用@required修饰
void testRequired2(String name, [@required int age]) {
print(‘姓名:$name 年龄:$age’);
}
/// content 预选参数
/// size、bold命名参数 通过{}
void testStyle1(String content, {double size, bool bold}) {
print(content + “ “ + size.toString() + “ “ + bold.toString());
}
/// size、bold位置参数 通过[]
void testStyle2(String content, [double size, bool bold]) {
print(content + “ “ + size.toString() + “ “ + bold.toString());
}
void defParam1(String name, [String sex = ‘男’, int age = 11]) {
if (age <= 18) {
print(‘姓名:$name 性别:$sex 年龄:$age’);
} else {
print(‘姓名:$name 性别:$sex 年龄:年龄保密’);
}
/// print(‘执行结束’);
}
void defParam2(
{List list = const [‘小黄’, ‘小李’, ‘小王’],
Map map = const {‘小黄’: 18, ‘小杨’: 22, ‘小赵’: 33}}) {
print(list);
print(map);
}

2. main()函数

main函数通常作为顶级函数、应用程序的入口函数,Flutter应用程序也是从main()启动的,下面代码表示应用要启动MyApp类
void main() =>runApp(MyApp());
main函数返回void 并且有可选参数 List args
上面代码中的runApp函数启动了整个应用的根组件,这样应用程序的界面就兄这里开始渲染了。

3. 函数作为参数传递

main(List arguments) {
var list = const [22, 33, 44];
list.forEach((element) {
printIntValue(element);
});
print(‘————————————‘);
list.forEach(printIntValue);
/// f 相当于 printIntValue、printStringValue 而element 相当于 value
/// 源码可以看出 forEach
/// void forEach(void f(E element)) {
/// for (E element in this) f(element);
/// }
var strList = [‘A’, ‘C’, ‘E’];
strList.forEach((element) {
printStringValue(element);
});
print(‘————————————‘);
strList.forEach(printStringValue);
}
void printIntValue(int value) {
print(value);
}
void printStringValue(String value) {
print(value);
}

4. 匿名函数

没有函数名 作为函数参数传递使用
/// 匿名函数 参数 函数体
intList.forEach((value) {
/// 回调值 value
print(‘$value’);
});
intList.forEach((value) => print(‘$value’));
var map = {‘1’: 2, ‘2’: 2, ‘3’: 3};
map.forEach((key, value) {
print(‘key:$key value:$value’);
});
map.forEach((key, value) => print(‘key:$key value:$value’));

5. 函数作用域

Dart 的词法作用域(称为静态作用域)变量的作用域在定义的时候确定
作用域范围是由变量所处的代码块({})的层级决定的,层级越深作用域越小,层级越潜,作用域越大
var topLevel = ‘顶级变量’;/// 不被任何{}代码块包含的变量 称为顶级变量 其作用域最大
main() {
var mainLevel = ‘main变量’;
void myFunction1() {
var fun1 = ‘fun1变量’;
void myFunction2() {
var fun2 = ‘fun2变量’;
print(topLevel);
print(mainLevel);
print(fun1);
print(fun2);
}
myFunction2();
}
myFunction1();
}
输出结果:
顶级变量
main变量
fun1变量
fun2变量

6. 闭包

即使一个函数对象不在初始作用域内,也可以访问其作用域内的变量
main() {
/// 返回函数 add1 :(num i)=> 2 + i;
var add1 = addNum(2);
/// 返回函数 add2 :(num i)=> 3 + i;
var add2 = addNum(3);
/// 访问addNum 作用域内的变量
print(‘${add1(2) == 4}’);
print(‘${add2(2) == 5}’);
print(‘${add2(3) == 7}’);
}
Function addNum(num value) {
return (num i) => value + i;
}
执行结果:
true
true
false

7.检测函数是否相等

测试顶级函数 静态方法、实例方法是否相等
void topFn() {}
class A {
// 静态函数
static sFunc() {}
// 普通实例函数
func() {}
}
main() {
var x = topFn;
var y = topFn;
/// 顶层函数对象相等
print(x == topFn);
print(x == y);
x = A.sFunc;
/// 静态函数对象相等
print(x == A.sFunc);
var v = A();
var w = A();
var s = w;
x = w.func;
/// s指向w锁指向的A()的实例对象 x指向w所指向的A()的实例对象
/// 那么同一个实例下面的函数是相等的
print(s.func == x);
/// v指向A()的实例对象 w指向另一个新的A()实例对象
/// 不同实例的函数不相等
print(v.func == w.func);
}
执行结果:
true
true
true
true
false

8. 返回值

/// void 返回值不能被用_void test1() {}
/// 函数名前不指定返回值类型 返回值都是null_test2() {}

/// 如果函数体内部最后是返回值语句 即使函数名前不指定返回值类型 也会自动推到 为dynamic动态
/// 返回值类型会根据最后返回的数据的类型进行推导
/dynamic test3(int value) { return value 2;}/
dynamic test3(int value) {
return value
2;
}
main() {
_/// print(test1());/// 报错提示 This expression has a type of ‘void’ so its value can’t be used. _print(test2()); var intValue = test3(2);
if (intValue is int) {
print(‘intValue is int type…’); print(test3(2));
} else {
print(‘其它类型’);
}
}
执行结果:
null
intValue is int type…
4