一架梯子,一头程序猿,仰望星空!

Dart 函数与闭包


虽然Dart是面相对象编程语言,但是也支持函数式编程,支持独立定义函数,不一定要在类内部才能定义函数。

1.函数定义

语法:

返回参数类型 函数名(参数1, 参数2, 参数3...) {
   函数代码 
}

一个函数定义的例子:

// 定义函数add10,  包含一个int参数n
int add10(int n) {
  return n + 10; // 返回一个int类型数据
}

调用函数语法

函数名(参数1, 参数2, 参数3...);

例子:

// 调用add10函数,传入参数10, 函数返回值赋值给变量 d
var d = add10(10);

实际上Dart语言,函数定义也是允许忽略参数类型定义。

// 函数的返回值和参数类型都被忽略掉了
add10(n) {
  return n + 10;
}

Dart会推断参数的实际类型,但是不建议忽略参数类型,影响函数可读性,尽量少用。

2.函数参数

函数允许定义0个或者多个参数。

例子:

// 定义了两个String类型参数
String say(String from, String msg) {
  var result = '$from says $msg';
  return result;
}

调用函数:

// 调用say函数,并使用print函数打印函数返回值
print(say("Tizi", "welcome visit tizi365.com!")); 

输出:

Tizi says welcome visit tizi365.com!

3.函数命名参数

命名参数,就是我们可以在函数调用传参的时候,直接根据参数名传递参数,忽略参数定义的顺序。

命名参数定义的例子:

// 定义参数,使用命名参数定义
// 参数包括在 花括号{} 之间
void enableFlags({bool bold, bool hidden}) {
	// 忽略函数代码
}

调用函数例子:

// 命名参数语法:
//   参数名: 参数值
// 多个参数使用逗号分隔,参数顺序无关紧要。
enableFlags(hidden: true, bold: false); // 这里传入两个参数

4.可选参数和默认值

命名参数,默认都是可选参数,参数默认值都是null。

接上面的例子:

// enableFlags函数定义了两个命名参数。
// 这里仅传入一个参数
enableFlags(bold: false);

// 一个参数都不传
enableFlags();

使用 = 号 定义命名参数默认值

// 参数bold和hidden的默认值都定义为false
void enableFlags({bool bold = false, bool hidden = false}) {
	// 忽略函数代码
}

普通参数的可选参数和默认值例子:

// 定义了4个普通参数
// 使用[]包括起来的参数都是可选参数,通常放在参数最后面。
// 同样可以使用 等号= 定义参数默认值。
String say(String from, String msg,
    [String device = 'carrier pigeon', String mood]) {
  var result = '$from says $msg';
  if (device != null) {
    result = '$result with a $device';
  }
  if (mood != null) {
    result = '$result (in a $mood mood)';
  }
  return result;
}

5.闭包函数

闭包函数又叫匿名函数,就是没有函数名的函数,我们将闭包函数赋值给一个变量,通过变量名调用函数即可。

例子:

// 定义一个闭包函数,拥有a,b两个参数, 这里忽略了参数类型
var f = (a, b) {
    return a > b;  // 返回bool类型参数
};

// 调用闭包函数
f(1,2);

使用闭包函数遍历数组.

var list = ['apples', 'bananas', 'oranges'];
// 给forEach函数,传递一个闭包函数,用于处理list数组的每一个元素
list.forEach((item) { // 闭包函数接受一个item参数
  print('${list.indexOf(item)}: $item');
});

输出:

0: apples
1: bananas
2: oranges

6.箭头函数

箭头函数也是闭包函数的一种,如果闭包函数只有一个表达式的时候,可以使用箭头函数简写。

例子:

// 定义闭包函数
var f = (a, b) {
    return a > b;  // 函数只有一个表达式
};

// 上面例子改写成箭头函数, 这两个函数是等价的
var f = (a, b) => a > b;

箭头函数语法:

(参数1, 参数2 ...) => 表达式

箭头函数返回表达式计算结果。

7.闭包函数作用域

Dart语言允许多层函数嵌套,我们先看一个多层函数嵌套变量作用域的例子。

// 顶层作用域变量
bool topLevel = true;

void main() {
  // main函数作用域变量
  var insideMain = true;

  void myFunction() {
    // myFunction函数作用域变量
    var insideFunction = true;

    void nestedFunction() {
      // nestedFunction函数作用域变量
      var insideNestedFunction = true;

      // nestedFunction函数中可以访问上面所有层级中的变量。
      print(topLevel);
      print(insideMain);
      print(insideFunction);
      print(insideNestedFunction);
    }
  }
}

闭包函数类似,函数内部可以引用包含闭包函数的所有层级作用域中的变量,与闭包函数调用的位置无关。

闭包函数作用域例子:

// makeAdder 返回一个闭包函数
Function makeAdder(num addBy) {
  // 闭包函数访问addBy参数
  return (num i) => addBy + i;
}

void main() {
  // 创建一个闭包函数,绑定参数2
  var add2 = makeAdder(2);

  // 创建一个闭包函数,绑定参数4
  var add4 = makeAdder(4);

  // 分别调用两个闭包函数,并打印结果
  print(add2(3));
  print(add4(3));
}

输出:

5
7