2.2、Dart语言基础:函数与闭包

学习笔记,旨在于快速入门和学习Dart,其中可能会有理解错误,请指出,一起学习。

系列文章

2.1、Dart语言基础:变量、运算符
2.2、Dart语言基础:函数与闭包
2.3、Dart语言基础:面向对象
2.4、Dart语言基础:异步
2.5、Dart语言基础:库与包
...

一、概述

  • Dart中函数是一等公民,因此,其可当做函数参数,可复制给变量;

  • 函数声明(与C语言类似)

void sayHello(String name) {
  print('$name say hello!');
}

// Tom say hello!
sayHello('Tom'); 

虽然可以省略参数类型和返回值类型,但是推荐最好写明白。

  • 箭头函数
    当函数只有一条语句, 可以使用 箭头函数=> expr 进行简写。
void sayHello(String name) => print('$name say hello!');

// Tom say hello!
sayHello('Tom'); 
  • 返回值:如果没有显示返回,则默认返回null
    All functions return a value. If no return value is specified, the statement return null;

二、函数参数

  • 参数的类型分为两种: 位置参数(positional parameters)命名参数(named parameters)

1、命名参数

语法格式1:{param1, param2, …},如下

void introduce_1({String? name, int? age}) {
  print("$name and $age");
}

// 1、null and null
introduce_1();
// 2、null and 30
introduce_1(age: 30);
// 3、tom and 30
introduce_1(name: 'tom', age: 30);
  • 调用函数时,可选参数可以不传递,其默认为null

  • 命名参数,调用函数时的入参顺序 与定义的参数位置无关。

  • 参数必须为 可选类型(即用?标记);调用方式func(paramName: value);

void introduce_10({String name, int age}) {
  print("$name and $age"); 
}

// 编译器报错:类型不匹配的错误
Error: The parameter 'name' can't have a value of 'null' because of its type 'String', but the implicit default value is 'null'.
Error: The parameter 'age' can't have a value of 'null' because of its type 'int', but the implicit default value is 'null'.

必选参数

  • 标记为必须参数,关键字required
    函数调用时,required 参数 必须入参,否则编译报错。
void introduce_1_2({required String? name, int? age}) {
  print("$name and $age"); 
}

  // Error: Required named parameter 'name' must be provided.
  introduce_1_2(age: 30);  
  // tom and null
  introduce_1_2(name: 'tom');

默认参数

  • 支持 默认参数
    函数调用时,默认参数可传递也可不传递。
void introduce_1_1({String? name='def', int? age}) {
  print("$name and $age");
}

// 1、def and 30
introduce_1_1(age: 30);

// 2、tom and 30
introduce_1_1(name: 'tom', age: 30);

另一种语法格式:{param1: value1, param2: value2, ...},需要指定默认值

void introduce_2({name: 'err', age: 0}) {
  print("$name and $age");
}

  // 1、err and 0
  introduce_2();
  // 2、err and 30
  introduce_2(age: 30);
  // 3、tom and 30
  introduce_2(name: 'tom', age: 30);

2、位置参数(positional parameters)

void say_1(String from, String msg) {
  print('$from says $msg');
}

  // 1、tom says hello world!
  say_1('tom', 'hello world!');
  // 2、Error: Too few positional arguments: 2 required, 1 given.
  say1('tom');
  • 调用函数时,位置参数 必须传递全部参数,且顺序必须一致,类型也必须一致。
String say_1_1(String from, String msg, [String? device]) {
  var result = '$from says $msg';
  if (device != null) {
    result = '$result with a $device';
  }
  return result;
}

// 1、Bob says Howdy
print(say_1_1('Bob', 'Howdy')); 
// 2、Bob says Howdy with a smoke signal
print(say_1_1('Bob', 'Howdy', 'smoke signal'));
可选位置参数
  • 支持声明 可选的位置参数;语法格式:[可选位置参数列表],如上。
  • 调用时候,可选的位置参数可以不传递。
String say_1_2(String from, String msg, [String? device = 'iphone']) {
  var result = '$from says $msg';
  if (device != null) {
    result = '$result with a $device';
  }
  return result;
}
  // 1、Bob says Howdy with a smoke signal
  print(say_1_2('Bob', 'Howdy', 'smoke signal'));
  // 2、Bob says Howdy with a iphone
  print(say_1_2('Bob', 'Howdy'));
  • 可选位置参数,支持默认参数。如上

3、默认参数值

  • 位置参数 和 命名参数 都支持设置函数的默认值;语法格式:param = value ,具体如上。
  • 默认值只能是编译时常量, 如果没有提供默认值,则默认值为 null。
    The default values must be compile-time constants. If no default value is provided, the default value is null.

4、一个函数可以同时定义 命名参数位置参数

void sayHelloworld_1(String name, {int? age}) {
  print("$name say hello,and age is $age!");
}
// 1、tom say hello,and age is null!
sayHelloworld_1('tom');
  
// 2、tom say hello,and age is 30!
sayHelloworld_1('tom', age: 30);
  • 调用函数时,可选的命名参数,可以不传递。

三、匿名函数,Anonymous functions

  • 其他语言,被称为lambda 或 闭包closure。
  • 语法格式:
([[Type] param1[, …]]) { 
  codeBlock; 
}; 
const list = ['apples', 'bananas', 'oranges'];
list.forEach((item) {
  print('${list.indexOf(item)}: $item');
});

// 输出如下:
0: apples
1: bananas
2: oranges
  • 上面以数组的forEach遍历方法为例:
list.forEach(
    (item) => print('${list.indexOf(item)}: $item'));
  • 单一语句,可以是会用箭头函数

四、作用域(词法)

1、词法作用域 Lexical scope

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);
    }
  }
}
  • Dart 是一门词法作用域的编程语言,就意味着变量的作用域是固定的。
    Dart is a lexically scoped language, which means that the scope of variables is determined statically, simply by the layout of the code.

  • 可简单的从代码层次结构上看出来,即变量的作用范围,仅局限在其 花括号{} 内。
    You can “follow the curly braces outwards” to see if a variable is in scope.

2、词法闭包 Lexical closures

  • 闭包本质是一个函数对象,因此其可以 捕获变量 到 闭包的作用域内;即使函数在其原来作用域内使用。
    A closure is a function object that has access to variables in its lexical scope, even when the function is used outside of its original scope.

  • 函数可以 捕获 在其作用域范围内定义的变量。
    Functions can close over variables defined in surrounding scopes.

  • makeAdder() 捕获了 变量addBy 到闭包的作用域内。
    In the following example, makeAdder() captures the variable addBy. Wherever the returned function goes, it remembers addBy.

Function makeAdder(int addBy, String name) {
  return (int i) => '${addBy + i} $name';
}

  var add2 = makeAdder(2, 'aaa');
  var add4 = makeAdder(4, 'bbb');
  print(add2(3)); // 5 aaa
  print(add4(3)); // 7 bbb
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容