main 函数

1
2
3
4
// 每个应用程序都必须有一个顶层 main 函数 
// flutter 的入口函数

void main() => runApp(MyApp());

函数餐宿

  1. 可选参数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // 可选命名函数,可以不传这些参数
    // 如果一个参数是可选的,但是不能为 null,你需要为它提供一个 默认值。

    userSettings();
    // null
    // null

    void userSettings({String? page, String? str}) {
    print(page);
    print(str);
    }
  2. 必传参数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // 必传参数 可以用 required 修饰。 
    // 使用 required 有利于静态代码分析器进行检查

    userSettings(page: 1, str: "2");
    // 1
    // 2

    void userSettings({required int page, required String str}) {
    print(page);
    print(str);
    }
  3. 可选的位置参数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    // 使用 [] 将一系列参数包裹起来作为位置参数:

    assert(say('Bob', 'Howdy') == 'Bob says Howdy');

    assert(say('Bob', 'Howdy', 'smoke signal') ==
    'Bob says Howdy with a smoke signal');

    String say(String from, String msg, [String? device]) {
    var result = '$from says $msg';
    if (device != null) {
    result = '$result with a $device';
    }
    return result;
    }
  4. 默认参数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    // 可以用 = 为函数的命名参数和位置参数定义默认值,默认值必须为编译时常量,没有指定默认值的情况下默认值为 null。

    enableFlags(bold: true);

    void enableFlags({bool bold = false, bool hidden = false}) {}

    // 位置参数设置默认值
    assert(say('Bob', 'Howdy') == 'Bob says Howdy with a carrier pigeon');

    String say(String from, String msg, [String device = 'carrier pigeon']) {
    var result = '$from says $msg with a $device';
    return result;
    }

函数是一级对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 可以将函数作为参数传递给另一个函数
void printElement(int element) {
print(element);
}

var list = [1, 2, 3];
list.forEach(printElement);

// 1、2、3

// 可以将函数赋值给一个变量
var loudify = (msg) => '!!! ${msg.toUpperCase()} !!!';
// print(loudify("hello")); !!! HELLO !!!
assert(loudify('hello') == '!!! HELLO !!!');

匿名函数

  1. 大多数方法都是有名字的,比如 main()printElement()。你可以创建一个没有名字的方法,称之为 匿名函数Lambda 表达式Closure 闭包。你可以将匿名方法赋值给一个变量然后使用它,比如将该变量添加到集合或从中删除。
  2. 匿名方法看起来与命名方法类似,在括号之间可以定义参数,参数之间用逗号分割。
  3. ([[类型] 参数[, …]]) { 函数体; };
1
2
3
4
5
6
7
8
9
10
11
12
13
// 定义了只有一个参数 item 且没有参数类型的匿名方法。 List 中的每个元素都会调用这个函数,打印元素位置和值的字符串:

const list = ["apple", "bannle", "orguee"];
list.forEach((item) {
print('${list.indexOf(item)}: $item');
});

// 0: apple、1: bannle、2: orguee

// 如果函数体内只有一行返回语句,你可以使用胖箭头缩写法。
list.forEach((item) => print('${list.indexOf(item)}: $item'));

// 0: apple、1: bannle、2: orguee

词法作用域

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// Dart 是词法有作用域语言,变量的作用域在写代码的时候就确定了,大括号内定义的变量只能在大括号内访问

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

// 注意 nestedFunction() 函数可以访问包括顶层变量在内的所有的变量。

词法闭包

  1. 闭包 即一个函数对象,即使函数对象的调用在它原始作用域之外,依然能够访问在它词法作用域内的变量。
  2. 函数可以封闭定义到它作用域内的变量。接下来的示例中,函数 makeAdder() 捕获了变量 addBy。无论函数在什么时候返回,它都可以使用捕获的 addBy 变量。
1
2
3
4
5
6
7
8
9
10
11
12
13
/// Returns a function that adds [addBy] to the
/// function's argument.

var add2 = makeAdder(2);
var add4 = makeAdder(4);
// print(add2(3)); 5
// print(add4(3)); 7


Function makeAdder(int addBy) {
return (int i) => addBy + i;
}

测试函数是否相等

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 下面是顶级函数,静态方法和示例方法相等性的测试示例:

Function x;

// Comparing top-level functions.
x = foo;
// print(foo == x); true

// Comparing static methods.
x = A.bar;
// print(A.bar == x); true

// Comparing instance methods.
var v = A(); // Instance #1 of A
var w = A(); // Instance #2 of A
var y = w;
x = w.baz;

// These closures refer to the same instance (#2),
// so they're equal.
// print(y.baz == x); true

// These closures refer to different instances,
// so they're unequal.
// print(v.baz == w.baz); false

返回值

1
2
3
4
5
6
7
8
 所有的函数都有返回值。没有显示返回语句的函数最后一行默认为执行 return null;。

foo() {}
// print(foo()); null

String foo() {
return "ddd";
}