Dart中的运算符有两个比较特殊,一个是赋值运算??= ;另一个是条件表达式??

??=

如果为nil就赋值,如果有值就直接返回。

  1. void main() {
  2. var a;
  3. a ??= 10; ///如果当a为空的话就赋值10
  4. a ??= 5; /// 此时a已经有值了所以直接返回
  5. a ??= 1;
  6. print(a);
  7. }

image.png

??

如果左边有值就直接返回左边,如果左边没有值就直接返回右边

  1. void main() {
  2. var a;
  3. a ??= 10; ///如果当a为空的话就赋值10
  4. a ??= 5;
  5. a ??= 1;
  6. print(a);
  7. var b;
  8. b = 5;
  9. print(b ?? a); /// 如果左边有值返回左边,如果左边没有值就直接返回右边
  10. }

image.png

Function

Dart中的方法也是一个对象,返回值和参数类型可以省略。当方法的执行语句只有一句的时候,可以使用箭头函数=>表达式

  1. void main() => functionDemo();
  2. void functionDemo() {
  3. print('function');
  4. }
  5. void functionDemo() => print('function');

之前写C的时候定义一个sum函数,在Dart中参数类型可以省略,但是不建议这么写。

  1. void functionDemo() {
  2. print(sum(10, 10));
  3. }
  4. ///int sum(int a, int b){
  5. /// return a + b;
  6. ///}
  7. /// 省略了参数类型之后
  8. int sum(a, b){
  9. return a + b;
  10. }

image.png

可选参数

定义可选参数就必须带上形参的名字,传递参数的时候也必须带上形参的名字。

  1. void main() => functionDemo();
  2. void functionDemo() {
  3. print(sum(1));
  4. print(sum(1, b:2, c: 3));
  5. print(sum(1, c:3));
  6. }
  7. sum(int a, {var b,var c}) {
  8. b ??= 1;
  9. c ??= 2;
  10. return a + b + c;
  11. }

image.png
那么上面的sum函数的bc的类型能都是int呢?

  1. sum1(int a, {int b, intc}) {
  2. return a + b + c;
  3. }

image.png
结果直接报错不能为空。这个时候我们可以使用可以为空的类型nullability

  1. sum1(int a, {int? b, int? c}) {
  2. b ??= 1;
  3. c ??= 2; /// int?告诉编译器,已经处理了后面为空的情况
  4. return a + b + c;
  5. }

可选参数也可以有默认值

  1. sum1(int a, {int b = 0, int c = 0}) {
  2. return a + b + c;
  3. }

上面介绍的{}里面的可选参数都是没有顺序的,使用[]可以指定顺序

  1. sum2(int a, [int b = 0, int c = 0]) {
  2. return a + b + c;
  3. }
  4. print(sum2(1, 2, 3)); ///此时这么写就是按照a,b,c的顺序指定

方法作为参数传递

Dart万物皆对象,那么方法也是对象可以传递。

  1. void main() {
  2. var list = [1,2,3,4];
  3. forEachDemo(list, printElement);
  4. }
  5. forEachDemo(List list, void func(var element)){
  6. for(var e in list) func(e);
  7. }
  8. int b = 0;
  9. printElement(var a) {
  10. b++;
  11. print('元素$b = $a' );
  12. }

image.png

匿名函数

匿名方法说白了就是没有方法名称的方法!

  1. void main() {
  2. var list = [1,2,3,4];
  3. /// 第一种写法:
  4. var func = (){
  5. print('匿名方法');
  6. };
  7. func();
  8. /// 第二种写法:立即执行的方法、函数
  9. (() {
  10. print('我是一个立即执行的函数');
  11. })();
  12. }

image.png
匿名函数一般在什么场景下使用?上面介绍的方法做为参数传递,其实也可以写成这种匿名函数,虽然看起来像block(闭包), 但是还是跟block有区别的。

  1. void main() {
  2. var list = [1,2,3,4];
  3. int b = 0;
  4. forEachDemo(list, (var a) {
  5. b++;
  6. print('元素$b = $a');
  7. });
  8. }
  9. forEachDemo(List list, void func(var element)){
  10. for(var e in list) func(e);
  11. }

image.png

闭包

closure:定义在函数里面的函数就是闭包,闭包也是一个对象。
闭包的作用:可以访问外部函数的局部变量。

  1. funA() {
  2. int count = 0;
  3. return() =>print(count++); ///这个匿名函数就是闭包
  4. }
  5. void main() {
  6. var func = funA();
  7. func();
  8. func();
  9. func();
  10. func();
  11. }

如果闭包是值传递的话,那么每次调用的时候这里应该打印的都是0,那么实际上呢
image.png
所以闭包没有销毁之前,闭包内部访问的外部变量也不会被释放。

  1. void main() {
  2. var func = funA();
  3. func(); /// 0
  4. func(); /// 1
  5. func(); /// 2
  6. func(); /// 3
  7. var func1 = funA();
  8. func1(); /// 0
  9. func1(); /// 1
  10. func1(); /// 2
  11. }