学习笔记,旨在于快速入门和学习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、命名参数
语法格式:{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
; - 命名参数,调用函数时的入参顺序 与定义的参数位置无关。
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);
- 支持设定
默认参数
;函数调用时,默认参数
可传递也可不传递。
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');
- 标记为必须参数,关键字
required
; - 函数调用时,
required 参数
必须入参,否则编译报错。
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'.
- 参数必须为 可选类型(即用
?
标记);调用方式func(paramName: value)
;
语法格式2:{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
网友评论