二、Dart语法
函数
定义函数,建议定义返回类型
String getName() {
return 'qiuyanxi';
}
只有一个表达式的函数能够使用箭头函数简化
String getName() => 'qiuyanxi';
必要参数
String getName(String name, int age) => '$name$age';
getName('qiuyanxi', 10);
可选的位置参数
使用[]
表示可选的位置参数
void printThings([String? str, String str2 = 'default value']) {
assert(str == null);
assert(str2 == 'default value');
}
printThings();
命名参数
命名参数默认都为可选参数。如果是必要参数,则需要用required
定义函数时,使用{参数 1,参数 2}
来指定命名参数
String getName2({required String name, int? age = 10}) => '$name$age';
调用函数时,使用 参数名:参数
值指定命名参数
getName2(name: 'qiuyanxi');
默认参数
如果一个参数是可选的但是不能是 null,那么需要提供一个默认的值。没有默认值的情况下参数是 null
/// Sets the [bold] and [hidden] flags ...
void enableFlags({bool bold = false, bool hidden = false}) {...}
// bold will be true; hidden will be false.
enableFlags(bold: true);
默认值
只有可选参数才有默认值,默认值必须为 编译时常量,如以下的参数为默认的 List 和 Map,为了变成编译时常量,需要加上 const 关键字
void getList([List<int> list = const [1, 2, 3]]) {}
void getMap([Map<String, String> map = const {"name": "qiuyanxi"}]) {}
main函数
main 函数是每个 Dart 程序必须有的顶级函数,是程序的入口,main 函数返回值是void ,并且有一个List<String>
类型的可选参数。
可以通过命令行给 main 函数传递参数
hello-world.dart
void main(List<String> args) {
// 在命令行运行以下命令: dart hello-world.dart 1 test
print(args); //['1', 'test']
assert(args.length == 2);
assert(int.parse(args[0]) == 1);
assert(args[1] == 'test');
}
匿名函数
匿名函数被当做参数使用
const list = ['apples', 'bananas', 'oranges'];
list.forEach((item) {
print('${list.indexOf(item)}: $item');
});
使用匿名箭头函数当做参数使用
const list = ['apples', 'bananas', 'oranges'];
list.forEach((item) => print('${list.indexOf(item)}: $item'));
词法作用域
Dart 的作用域是词法作用域,跟 JavaScript 一样,在写代码的时候就确定了。
闭包
闭包也跟 JavaScript 一样,就不多介绍了。
返回值
所有函数都有返回值的,即使返回值是 void。如果没有明确写返回语句,那么默认执行return null
// 这是明确表示返回 void 的函数
void returnVoid() {
print('hello');
}
var a = returnVoid();
// void 类型的变量不能被使用
// print(a);
// 这是没有返回语句的函数
returnNull() {}
var b = returnNull();
assert(returnNull() == null); // true
运算符
赋值运算符
var a = 1;
int? b;
b ??= 2; // 如果 b 为空的话就把 2 赋值给 b
a += 0; // a=a+0
算数运算符
print(a + b);
print(a - b);
print(a * b);
print(a / b);
print(a % b); // 取余
print(a ~/ b); // 取整
a ++ // 先运算再自增
a -- //先运算再自减
-- a // 先自减再运算
++ a // 先自增再运算
关系运算符
print(a == b);
print(a >= b);
print(a <= b);
print(a != b);
identical(DateTime.now(), DateTime.now()); // 判断两个对象是否相等
类型判断运算符
Operator | Meaning |
---|---|
as |
类型转换(也用作指定 类前缀)) |
is |
如果对象是指定类型则返回 true |
is! |
如果对象是指定类型则返回 false |
逻辑运算符
运算符 | 描述 |
---|---|
!*表达式* |
对表达式结果取反(即将 true 变为 false,false 变为 true) |
|| |
逻辑或 |
&& |
逻辑与 |
var c = false;
var d = true;
/* 取反 */
if (!c) {
print(c);
}
/* && 并且 */
if (c && d) {}
/* || 或 */
if (c || d) {}
表达式
表达式 1 ?? 表达式 2
如果表达式1 为 null 则返回表达式 2
/* ??运算符 */
var i;
var j = i ?? 10; // i 为空则将 10 赋值给 j,同 js 空值合并运算符
print(j);
条件 ? 表达式 1 : 表达式 2
/* 三目运算符 */
var flag;
flag = true;
var f = flag ? 'true' : 'false';
级联运算符
级联运算符 (.., ?..
) 可以让你在同一个对象上连续调用多个对象的变量或方法。
下面代码
var paint = Paint()
..color = Colors.black
..strokeCap = StrokeCap.round
..strokeWidth = 5.0;
/* 相当于 */
var paint = Paint();
paint.color = Colors.black;
paint.strokeCap = StrokeCap.round;
paint.strokeWidth = 5.0;
querySelector('#confirm') // Get an object.
?..text = 'Confirm' // Use its members.
..classes.add('important')
..onClick.listen((e) => window.alert('Confirmed!'));
/* 相当于 */
var button = querySelector('#confirm');
button?.text = 'Confirm';
button?.classes.add('important');
button?.onClick.listen((e) => window.alert('Confirmed!'));
其他运算符
运算符 | 名字 | 描述 |
---|---|---|
() |
使用方法 | 代表调用一个方法 |
[] |
访问 List | 访问 List 中特定位置的元素 |
?[] |
判空访问 | List 左侧调用者不为空时,访问 List 中特定位置的元素 |
. |
访问成员 | 成员访问符 |
?. |
条件访问成员 | 与上述成员访问符类似,但是左边的操作对象不能为 null,例如 foo?.bar,如果 foo 为 null 则返回 null ,否则返回 bar |
判空
判断字符串是否为空
var str = ''; if (str.isEmpty) { print(' 判断为空字符串'); }
判断是否为 null
var _null = null; if (_null == null) { print('判断为 null'); }
判断是否为 NaN
var _nan = 0 / 0; if (_nan.isNaN) { print('是 NaN'); }
空安全
Dart 目前支持控安全机制,也就是说除非我们声明它可空,否则它们的值不能为空,这样做的好处是提高了代码的健壮性,在编译的时候就能报错。
空安全需要 dart 在 2.12 以上
声明可空的方式就是在类型前面加个问号:
int? count;
count = null;
如果没有加问号,那么这个值就不能是空的
int count;
// ❌ A value of type 'Null' can't be assigned to a variable of type 'int'.
count = null;
如果我们知道一个值不可能为空,但是 Dart 判断可能为空,那就用!表示非空断言
String? getData(String? data) {
if (data is String) {
return 'this is string data';
}
return null;
}
- String a = getData('12131');
+ String a = getData('12131')!;
流程控制语句
for 循环
for (var i = 0; i < 10; i++) { print(i); }
JavaScript 的 var 在 for 循环中只有一个作用域,dart 的 var 不存在这个问题,所以上面的代码能够正常打出
i
的值。for...in 循环
使用 for..in 遍历可迭代对象,比如 Lists 类型和 Set 类型
var list = [1, 2, 3]; var sets = <int>{1, 2, 3}; for (var value in list) { print(value); } for (var value in sets) { print(value); }
可迭代对象也可以使用
forEach
方法循环var collection = [1, 2, 3]; collection.forEach(print); // 1 2 3
while 循环
var i = 10; while (i > 0) { print(i); i--; }
do while 循环
do { print(i); i--; } while (i > 0);
do while 跟 while 的区别是即使不满足条件,do while 循环也会 do 一次;while 循环不会
var i = 0; do { print(i); //这段代码执行了 i--; } while (i > 0); while (i > 0) { print(i);// 永远不会执行 i--; }
break,continue 语句
break 跳出循环,continue 跳过本轮循环
switch和 case
断言——assert
assert(1 < 2); assert(1 > 2, '1>2 is wrong');
异常捕获
Dart 提供 Exception 和 Error 两种类型的异常以及一些子类。我们可以自己定义异常类型,也可以将任何非 null 对象作为异常抛出。
抛出异常
throw new Exception('这是一个异常报错'); throw '这是一个异常报错';
捕获异常
try { // throw Error(); throw Exception('this is exception error'); } on Exception catch (e) { print('this is Unknown exception $e'); } catch (e,s) { print('No specified type, handles all error $e'); print('Stack trace:\n $s'); }
上面的代码使用 on 和 catch 来捕获异常,on 来指定异常的类型,catch 则用来捕获对象。当抛出的错误并不是 on 指定的异常类型时,则走最后面的 catch 兜底。
catch 方法有两个参数,第一个参数是抛出的异常对象,第二个参数是栈信息。
rethrow 再次抛出异常
当我们在捕获到一个异常时,还可以再次将这个异常抛出。
下面的例子将内层函数捕获的异常抛出到外部作用域让 main 函数里的代码捕获到。
void misbehave() { try { dynamic foo = true; print(foo++); // Runtime error } catch (e) { print('misbehave() partially handled ${e.runtimeType}.'); rethrow; // Allow callers to see the exception. } } void main() { try { misbehave(); } catch (e) { print('main() finished handling ${e.runtimeType}.'); } }
上面的代码会打印出如下信息:
misbehave() partially handled NoSuchMethodError. main() finished handling NoSuchMethodError.
Finally
无论是否抛出异常,都会执行 finally 语句。
try { throw Error(); } catch (e) { print('i will catch this error'); } finally { print('finally print this message'); }