二、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');
      }
    

results matching ""

    No results matching ""