Dart 基础语法入门

Dart简介

  • Dart是谷歌开发的,类型安全的,面向对象的编程语言,被应用于Web、服务器、移动应用和物联网等领域。
  • Dart诞生于2011年10月10日
  • Dart和java一样属于强类型语言,可以进行类型推断
  • Dart由Dart VM虚拟机执行,可以运行在window、mac、linux上。
  • 全平台语言,可以很好胜任移动和前后端的开发

Dart 搭建

  • flutter最新版已经内置了dart的sdk,在\flutter\bin路径下,之后再配置下dart环境变量,就能更方便使用dart命令行。
  • Dart项目命名规则:带下划线的小写字母

Dart基础用法

  • Dart是一门面向对象的语言,每个对象都是一个类的实例。数字、函数以及nulll都是对象。除了null外(如果开启了空安全),所有类都继承于Object类,默认值为null。

  • Dart从2.12开始支持空安全(null safety)的特性,由于空安全的限制,如果指定不进行初始化,则会报错,因此要加一个可空符号 "?"例如int?声明的变量可以是整数也可以是null。

  • Dart 支持泛型,比如数组的泛型:List表示由 int 对象组成的列表或List表示由任意类型对象组成的列表

  • Dart 没有 public、protected 和 private 成员访问限定符。想要表示私有的,则用_当做标识符放在变量声明前面,并且类要独立一个文件这个属性才能生效。(补充:在flutter框架中有提供一个@protected注解(该注解只会发出警告,同时会引入flutter相关检查规则,在package项目会报一些缺少相关文件的错误)

  • Dart支持泛型,例如List表示任意类型对象组成的列表

    变量

    • 1、使用var 声明变量,可以赋予不同类型的值,var可以在运行中推导出变量的类型,确定了便不能更改类型

    • 2、使用Object,这个关键字大家应该都很熟悉,Java中的所有对象的父类就是Object,Object和var不同的点是即使赋了初始值,也可以指定别的类型,例如int,String,Num等。

    • 3、dynamic 和Object非常类似,唯一的区别就是如果你调用一个本身不存在的方法,Object会在编译器就直接报错,而dynamic则会在运行的时候才会抛出异常

      ini 复制代码
        //var定义变量
        var name = 3;
        name = "Bob"; // 编译报错:A value of type 'String'can't be assigned to a variable of type 'int'.
        //Object定义变量
        Object a = 'blob';
        a = 123;
        a = [];
        //  动态定义变量
        dynamic _name = 'Bob';
        _name = 3;
        // object和dynamic的区别
        Object testa = "asd";  
        // testa.substring(1);//编译失败:The method 'substring' isn't defined for the type 'Object'.  
          //正确1强转 :print("Object>>>>"+(testa as String).substring(1));  
        dynamic testdy = "restdy";  
         print(testdy.substring(1));//编译通过
         

    常量

    • 常量在dart中可以用final和const来修饰
    • final包含了const的功能,区别在于 1、final可以接受运行时的数据,const则只能接受编译时的数据 2、const 必须给一个明确的编译常量值(即编译期间就确定的值),final 可以一开始不赋值。 3、final 是惰性初始化,运行时第一次使用前才进行初始化 4、const在修饰类中变量时,则必须加上static变量
    JavaScript 复制代码
    //-----第一点:-----
    final time = DateTime.now();
    // const time2 = DateTime.now();//编译报错:Const variables must be initialized with a constant value.
     
     //-----第二点:-----
     
     //正确
      const atest = 1;
      const btest = atest > 1 ? 2 : 1;
    //错误
      var atest2 = 1;
      //下面这句报错:Const variables must be initialized with a constant value
      // const btest2 = atest2 > 1 ? 2 : 1;
    
    //如果字符串是const 声明的编译时常量,编译时常量 (null、数字、字符串、布尔) 才可以作为该字符串字面量的插值表达式。
    // 这些在 const 声明的字符串常量中能用
      const aConstNum = 0;
      const aConstBool = true;
      const aConstString = 'a constant string';
    // 这些在 const 字符串中不能用,用 var 声明的才有用
      var aNum = 0;
      var aBool = true;
      var aString = 'a string';
      const aConstList = [1, 2, 3];
      const validConstString = '$aConstNum $aConstBool $aConstString';
      //编译出错:In constant expressions, operands of this operator
      // must be of type 'bool', 'num', 'String' or 'null'.
      // const invalidConstString = '$aNum $aBool $aString';
      var validConstString2 = '$aNum $aBool $aString $aConstList';
      print(validConstString2);
    
    
    //--第三点-----
    
    // const a; //编译报错: The constant 'a' must be initialized.
    	final testfinal;
    	testfinal = "3";
    
    //第四点
    class Test{
       const String name="jack";//报错提示:尝试将字段声明为
       //最终字段,或添加关键字"静态"。
    
      void getString(){
        const String name2="jack";
      }
    
    }

    5、final 只可用来修饰变量, const 关键字不仅仅用来定义常量,还可以用来创建常量值,该常量值可以赋予给任何变量。也可以将构造函数声明为 const,这种类型的构造函数创建的对象是不可改变的。 6、const 修饰对象时,要在构造方法加const

    JavaScript 复制代码
    //5、const修饰的数组列表不能被修改
    	var foo = const [1,2,3];
    	// foo[0] = 3;//报错:Cannot modify an unmodifiable list
    	// print("foo:{$foo}");
    	
    	//final定义的数组列表可以被修改
    	final bar =  [1,3,4];
    	bar[0] = 9;
    	print("bar:${bar}");//正确
    
    	//一样不能被修改
    	final barconst = const [];
    	// barconst[0] = 9;//报错:Cannot modify an unmodifiable list
    
    	const baz = []; // 相当于`const []`
    	baz.add("value");
    	print(baz);//报错:Cannot add to an unmodifiable list
    
    	//const 修饰对象
    	//const 修饰对象时,要在构造方法加const
    	//否则会报:Cannot invoke a non-'const' constructor where a const expression is expected.
    	
    	const p1 = const Person('myname');
    	const p2 = Person('myname'); // 右边的const 可以省略
    	var p3 = const Person("myname");
    
    	print("---------${identical(p1, p2)}");// true
    	print("---------${identical(p1, p3)}");// false
    • 关于identical函数(检查两个引用是否指向同一个对象。)
    JavaScript 复制代码
    //官方说明
    var o = new Object();
     var isIdentical = identical(o, new Object()); // false, different objects.
     isIdentical = identical(o, o); // true, same object
     isIdentical = identical(const Object(), const Object()); // true, const canonicalizes
     isIdentical = identical([1], [1]); // false
     isIdentical = identical(const [1], const [1]); // true
     isIdentical = identical(const [1], const [2]); // false
     isIdentical = identical(2, 1 + 1); // true, integers canonicalizes

    关键字

    • 带有上标1的是上下文关键字,仅在特定位置具有含义。它们是可以在任何地方作为标识符。
    • 带有上标2的单词是内置标识符。为了简化将JavaScript代码移植到Dart的任务,这些关键字在大多数地方都是有效的标识符,但它们不能用作类或类型名称,也不能用作导入模块时的前缀。
    • 带有上标3的单词是与Dart 1.0发布后添加的异步支持相关的关键字。

    part和part of

    这个关键字可以把文件分成多个文件,将一个大的lib拆分成多个小的文件

    注意part跟part of 要配套使用

    • A类
    Dart 复制代码
        part "B.dart"//指明B是A的一部分
    • B类
    Dart 复制代码
        part of "A.dart"//指明B是属于A的一部分

    运算符

    JavaScript 复制代码
      //赋值运算符
      var a = 1;
      int? b;
      print(b);//null
      b ??= 2; // 如果 b 为空的话就把 2 赋值给 b
      print(b);//2
      a += 0;
      print(a);//1
    
    //  算数运算符
    //a=1,b=2
      print(a + b);//3
      print(a - b);//-1
      print(a * b);//2
      print(a / b);//0.5   在java中会进行取整运算,在dart中会自动推导成小数
      print(a % b); // 取余  1
      print(a ~/ b); // 取整 0 ===>和java的取整一样
      //以下和java一样
      // a++ // 先运算再自增
      // a-- //先运算再自减
      // --a // 先自减再运算
      // ++a // 先自增再运算
    
      print("========关系运算符========");
      ////a=1,b=2
      //关系运算符
      print(a == b);//false
      print(a >= b);//false
      print(a <= b);//true
      print(a != b);//true
      // print(identical(DateTime.now(), DateTime.now())); // 判断两个对象是否相等
    
      print("========类型判断运算符========");
      // 类型判断运算符
      //as 类型转换(也用作指定 类前缀))
      //is 如果对象是指定类型则返回 true
      //is! 如果对象是指定类型则返回 false(取非运算)
      var num = 3;
      var testop = TestOp();
    
      print(num is TestOp);//false
      print(testop is TestOp);//true
    
      // print("========逻辑运算符========");
    
    //  ! 非 && 与 || 或
    
      print("========表达式========");
    //表达式
      //表达式 1 ?? 表达式 2   表达式1为null,返回表达式2
      //条件 ? 表达式 1 : 表达式 2   三目运算符
      var i;
      var j = i??10;
      print(j);//10
    
      var testh = 0/0??2;
      print(testh);//NaN
    
      //变量1??= 变量2  变量1为null,把变量2赋值给1
      var ai;
      ai??=100;
      print(ai);//100
    
      // var test3 = 0 * i ?? 12; // 报错:'Null' is not a subtype of type 'num'
      var test4 = 0/0;
      print(test4 is Object); // true
    
      var flag;
      flag = true;
      var f = flag ? 'true' : 'false';
      print(f);//true
    
    
      print("========级联运算符========");
    //级联运算符 (.., ?..) 可以让你在同一个对象
    // 上连续调用多个对象的变量或方法。
    //  有点像Builder模式
    //   var paint = Paint()
    //   ..color = Colors.red // 这里不能加;
    //   ..strokeCap = StrokeCap.round
    //   ..strokeWidth = 5.0;
    
      var test = TestOp() // Get an object.
        ?..text = 'Confirm'; // Use its members.
    
      print(test);
      /* 相当于  */
      var button;
      button?.text = 'Confirm';//?为null的时候断路, !则相反,为null的时候,直接报错
      print("button>>$button");
    
      var list;
      print(list?[1]);//null  ?[] 左侧调用者不为空时,访问 List 中特定位置的元素

    数据类型

    • Numbers类型:int 整型和 double 浮点类型
    • Strings类型:String
    • Booleans类型:bool
    • Lists类型:List
    • Maps类型:Map类型
    • Sets类型:Set
    • Symbols类型:Symbol
    • Null:null
    • Runes:常用于在 Characters API 中进行字符替换

    Number

    • int为整形,double为浮点型,dart中没有float 数字类型是num的子类,num提供了一些基本的运算符和方法,具体可以看dart:math 库的api
    • double可以兼容整形,但是值是整形的话,会自动转换成浮点数
    • num不会自动转换成浮点数
    • 数字转字符串可以用:toString()
    • 字符串转数字:parse
    • num如果和要赋值的对象值不是同一种类型,则不能直接使用as强转成int或者double,而要使用toInt()\toDouble()等Api
    JavaScript 复制代码
    	// Numbers类型:int 整型和 double 浮点类型
    	//如果想要声明一个类型是数字类型,既可以是整型也可以是浮点数,则可以用num类型
    	num x = 1;
    	x += 2.5;
    	print(x); // 3.5
    	// 如果声明一个 double 类型,但是值是整型的话,会自动转换成浮点数。
    	double y = 3;
    	print("y:$y");//输出3.0
    
    	// 数字转字符串:toString()
    	int a = 123;
    	double b = 123.23;
    	String _a = a.toString();
    	String _b = b.toString();
    	//String _c = a+"";//编译出错:A value of type 'String' can't be assigned to a variable // of type 'num'.
    	print("_a>>>$_a");
    	print(_a == '123');
    	print("_b>>>$_b>>>>${_b == "123.23"}");
    
    	//字符串转数字
    	String areserve = '123';
    	String breserve = '123.23';
    	int _areserve = int.parse(areserve);//
    	print("_areserve == 123?  ${_areserve == 123}");
    	double _breserve = double.parse(breserve);
    	print("_breserve == 123.23?  ${_breserve == 123.23}");
    	
    	//num 转int
    	  num yx = 9;
    	  int yyi = yx as int;//正确
    
    	  num yx = 9.9;
    	  int yyi = yx as int;//错误
    	  //正确方式
    	  int yyi = yx.toInt();

    String类型

    • 字符串可以用单/双引号,在双引号中使用单引号可以不用转义,反之亦然。
    • 字符串拼接可以用** <math xmlns="http://www.w3.org/1998/Math/MathML"> ∗ ∗ 或者 ∗ ∗ **或者** </math>∗∗或者∗∗{} +,具体用法是${表达式}**,单变量可以省略{},如果表达式结果是对象,则会自动调用toString方法获取一个字符串。
    JavaScript 复制代码
    	var s1 = '使用单引号创建字符串字面量。';
    	var s2 = "双引号也可以用于创建字符串字面量。";
    	var s3 = '使用单引号创建字符串时可以使用斜杠来转义那些与单引号冲突的字符串:\'。';
    	var s4 = "而在双引号中则不需要使用转义与单引号冲突的字符串:'";
    	print("$s1\n$s2\n$s3\n$s4");
    	// var s5 = "测试"+3;//The argument type 'int' can't be assigned to the parameter type 'String'
    	var s6 = "测试"+'3';
    
    	var maps={
    	  "name":"小明"
    	};
    	print("maps的值为$maps"); // map的值为{name: 小明}
    	String s7 = "this is demo";
    	print("${s7.toUpperCase()}"); //THIS IS DEMO
    
    	//三个单引号或者三个双引号能创建多行字符串
    	  var s8 = '''
    	You can create
    	multi-line strings like this one.
    	''';
    	/**
    	 *   You can create
    		multi-line strings like this one.
    	 */
    	print(s8);
    
    	  var s9 = """This is also a
    	multi-line string.""";
    	/**
    	 * This is also a
    		multi-line string.
    	 */
    	print(s9);
    
    
    	// 如果希望字符串中的内容不会被做任何处理(比如转义),则可以在字符串前面加上 r 来创建 raw 字符串
    	var s10 = r'在 raw 字符串中,转义字符串 \n 会直接输出 "\n" 而不是转义为换行。';
    	print(s10); //在 raw 字符串中,转义字符串 \n 会直接输出 "\n" 而不是转义为换行。
    
    	//如果字符串是const 声明的编译时常量,编译时常量 (null、数字、字符串、布尔) 才可以作为该字符串字面量的插值表达式。

    Booleans类型:bool

    • Dart 的条件判断跟 JavaScript 不太一样,JavaScript 可以用 falsy值做条件判断,而dart需要用bool型或者返回bool型的值才能做判断
    • dart判断是否是空字符串(isEmpty),判断是否是NaN(isNaN),是否是null(== null)

    JavaScript中的bool判断

    JavaScript 复制代码
    0、''、false、undefined、null、-0、NaN // javascript 的 falsy 值
    
    // 比如:
    let a;
    if (!a) {
      console.log(`a为${a}`); // a为undefined
    }

    Dart中的bool判断

    JavaScript 复制代码
    String? a = null; // Conditions must have a static type of 'bool'.Try changing the condition 
    // ❌ 条件必须是bool 类型
    /* if (a) { print(a); }
    else { print(a); } */
    
    //正确
     bool b;
      bool getResult() {
        return true;
      }
    
      b = getResult();
      if (b) {
        print(b);
      } else {
        print(b);
      }
      
      var fullName = '';
    print("fullName.isEmpty is ${fullName.isEmpty}");//fullName.isEmpty is true
    //检查是否为空
    var hitPoints;
    print("hitPoints == null?>>>${hitPoints == null}");//hitPoints == null?>>>true
    
    var iMeantToDoThis = 0 / 0;
    print(iMeantToDoThis.isNaN);//true

    Lists 类型:List

    • 跟 JavaScript 中的数组差不多,Dart 的数组也是封装后的Object特殊类,并不是传统意义上的数组。
    • 扩展操作符为:...,如果变量为可空,则应该加上空感知操作符**...?**
    • 在Dart语言中,还允许在列表中使用for以及if
    JavaScript 复制代码
     var arr = <String>['0', '1', '2', '3']; // 定义数组类型
       // var arr3 = <String>[0,'3',true,1];//编译报错
      var arr1 = [0, 1, 2, 3, 4]; //自动推断
      var arr2 = [0,'3',true,1];
      // List arr5 = <Bool>[new Bool(),Bool(),Bool(),Bool()];// 使用类型的方式定义list
    
    
      print(arr);//[0, 1, 2, 3]
      print(arr1);// [0, 1, 2, 3, 4]
      print(arr2);//[0, 3, true, 1]
    
    
      var arr5 = const [1, 2, 3, 4]; // 创建一个编译时的常量,不能修改、增加
      // arr5.add(5); // Cannot add to an unmodifiable list
    
    
      var arr6 = List.filled(2,'');// 创建一个固定长度的集合
      var arr7 = List<int>.filled(2,0);// 创建一个固定长度的有类型的集合
      
      print("arr6 is $arr6,and length is ${arr6.length}");//arr6 is [, ],and length is 2
      print("arr7 is $arr7,and length is ${arr7.length}");//arr7 is [0, 0],and length is 2
    
    	var arr9 = List.filled(2,Object());// 需要注意的是,使用这种方式创建,会把所有的元素设置为同一个,地址也指向的同一个
    	print("是否相等${arr9[0] == arr9[1]}");//true
    
    
      //扩展列表
      var list = [1, 2, 3];
      var list2 = [0, ...list]; // 将 list 插入 list2 中
      print("list2 is $list2,and length is ${list2.length}");//list2 is [0, 1, 2, 3],and length is 4
    
    
      var list3;
      var list4 = [0, ...?list3];
       // var list4 = [0, ...list3];//报错: type 'Null' is not a subtype of type 'Iterable<dynamic>'
      print("list2 is $list4,and length is ${list4.length}");//list2 is [0],and length is 1
    
    
    //这里需要注意的是如果if和for加了大括号,那么dart将会认为{}是一个Set的数据类型,
    //在list中使用for
    var listOfInts = [1, 2, 3];
    var listOfStrings = ['#0', for (var i in listOfInts){
      if(i != 2){
        '#$i'
      }else{
        '#2222'
      }
    }];
    print(listOfStrings); //[#0, {{#1}}, {{#2222}}, {{#3}}]
    
      // 在 List 中可以使用 if 或 for
      var changed = 10 + 10 == 30;
      var nav = ['Home', 'Furniture', 'Plants', if (changed) 'Outlet'else 'Inputlet'];
      print("nav is $nav,and length is ${nav.length}");//nav is [Home, Furniture, Plants, Inputlet],and length is 4
    
      //在list中使用for
      var listOfInts = [1, 2, 3];
      var listOfStrings = ['#0', for (var i in listOfInts) '#$i'];
      print(listOfStrings); // [#0, #1, #2, #3]
    // ...其他api参照官网

    Sets数据类型

    • set类似于java里面的Set列表,本质是剔除数据里面的重复元素。
    • set是以 {} 的形式来体现的,例如{},或者将 {} 赋值给Set类型的变量
    • 使用add或addAll等api可以添加元素
    • 使用.length可以获取到元素个数
    • set也可以使用扩展操作符以及空感知操作符
    • set也可以在里面使用for,用法和list一样
    JavaScript 复制代码
    // Sets类型:Set
      var testset2 = {'1','2','3'};
      var testset = {'testfor',for(var j in testset2) '测试#$j'};
    
      print(testset);
    
      var halogens = {'fluorine', 'chlorine', 'chlorine', 'chlorine', 'chlorine','a','a','b'};
      Set sets = <String>{'fluorine', 'chlorine','fluorine',...halogens};
      print(sets);//{fluorine, chlorine},去除重复值
    
      //在{}前面加类型参数可以创建一个set,或者将{}赋值给一个Set变量。
      var s = <String>{};
      Set _s = <String>{};
      Set<String> names = {};
      print(names);//{}
      var _names = {}; // 这是一个 map 不是 set
      print(_names);//{}
      print("${_names is Set} ====> ${_names is Map}"); // false ====> true
    
      var settest = {"2","31"};
      print(settest);//{2, 31}
      print("${settest is Set} ====> ${settest is Map}"); // true ====> false
    
    
    
      //使用add方法或者addAll方法可以添加元素
      var sets2 = <Object>{};
      sets2.add('1');
      sets2.addAll([1, 2, 3]);
      print(sets2);//{1, 1, 2, 3}
    
      //Set 可以使用扩展操作符和空感知操作符
      final sets3 = {'fluorine', 'chlorine'};
      var maybeNull;
      final seta = <String>{'hello', ...sets3};
      final setb = <String>{'hello', ...?maybeNull};//如果写成...maybeNull 则会报错:type 'Null' is not a subtype of type 'Iterable<dynamic>'
      print(seta);//{hello, fluorine, chlorine}
      print(setb);//{hello}

    Map数据类型

    • Map类型和JavaScript的Map数据结构类似
    • Map是以 {} 为表现形式的,如{'name': '123'} 、 <int,String>{1,"3"}
    • Map也可以以Map()、Map<int, String>()的形式出现
    • Map赋/取值可以用map[key]的形式
    • Map可以存null、0/0(NaN)而不会报错
    • containsKey判断是否有key,如果有则返回ture,由于map可以插入 {"key5":null} 这种数据形式,所以map['key5']等于null并不能说明map中是否存在这个key,但这api就能对这种情况进行正确的判断。
    • Map也可以使用扩展运算符和空感知操作符
    JavaScript 复制代码
    const amap = [1, 2, 3];
      var mapT = {amap: '123'}; 
      var map1 = <String,String>{'a': '123'};
      var map2 = Map(); // 创建自由类型的 map,可以加 new
      var map3 = Map<int, String>(); // 创建 map 时定义类型
      map3[10] = '1222'; // 给 map 赋值
      print(mapT);//{[1, 2, 3]: 123}
      print(map1);//{a: 123}
      print(map2);//{}
      print(map3);//{10: 1222}
      print(mapT.containsKey(amap)); //true
      print(mapT['ad312e32']);
      var page_info = Map();
      var seo = 'test';
      page_info[seo] = {
        "keywords": "infoq、Map",
        "description":"Map对象是一种简单的键/值映射,其中的键和值可以是任意值(原始值或对象的值)"
      };
      print("page_info $page_info");//page_info {test: {keywords: infoq、Map, description: Map对象是一种简单的键/值映射,其中的键和值可以是任意值(原始值或对象的值)}}
    
      var map4 = Map();
      map4['key1'] = 'value1';
      map4['key2'] = 'value1';
      map4['key3'] = 'value1';
      map4['key2'] = 'value10';
      print(map4);//{key1: value1, key2: value10, key3: value1}
      //添加多个属性
      map4.addAll({"name": '小张', 1: 2});
      print(map4);//{key1: value1, key2: value10, key3: value1, name: qiuyanxi, 1: 2, null: null, NaN: asd, key5: null}
    
      print(map4['key4']);//没有key的情况下会返回null
      print(map4.containsKey('key4'));//没有key的情况下会返回false
      map4[null] = null;//可插入null值
      map4[0/0] = "asd";
    
      map4['key5'] = null;
      print("map4$map4");//{key1: value1, key2: value10, key3: value1, name: qiuyanxi, 1: 2, null: null, NaN: asd, key5: null}
      print(map4['key5']);//返回null
      print(map4.containsKey('key5'));//返回true

    Runes类型

    • 常用于在 Characters API 中进行字符替换
    • Dart字符串是UTF-16的字符序列,如果要使用UTF-32字符集可以使用Runes
    • UTF-32一般使用 \uxxxx 来表示, 如心形符号是\u2665,如果非4个数值,如:\u{1f605},需要把编码值放到大括号中。
    JavaScript 复制代码
    Runes runes = new Runes('\u{1f605} \u6211');
      var str1 = String.fromCharCodes(runes);
      print(str1);

    Symbol标识符

    • 以前主要是反射使用,但是现在mirrors模块已经被移除,所以没啥大用了,大家只要知道有这么一个内置类型就可以了

    获取类型

    • 获取类型在dart中可以使用runtimeType来获取
    JavaScript 复制代码
      var n = null;
      var s = 'String';
      print(n.runtimeType); // Null
      print(s.runtimeType); // String

    函数

    • 函数的定义:函数在Dart中也是一个对象,它的类型是Function,这就意味着函数可以传递给其他变量,这个和JavaScript有点类似。
    • 可以函数内定义
    • 定义函数时可省略类型(不建议)
    • Dart函数不允许重载,也就是说同一个类中不允许有同名函数,这点和java有些许不同
    • 函数也可以用 _ 来表示私有private
    • Dart中的函数可以使用箭头函数表达。
    • 函数的参数分为必选参数和可选参数,可选参数里面又包含位置可选参数以及命名可选参数。
    • 可选命名参数定义函数是语法为**{参数1,参数2},调用时,语法为参数名:参数值**
    • 可选位置参数使用**[]**来表示。
    • 必选参数和可选位置参数在同一个函数体内,必选参数要在可选位置参数之前,不然会报错
    JavaScript 复制代码
    //函数内定义
    void main(){
      void test(){
      }
    }
    //不返回类型,默认返回null
    main(){
      test(){
        // return null;
      }
    }
    void main(){
      print(getName());
    }
    String getName() {
      return '李四';
    }
    /**
     * 报错:'getName' is already declared in this scope.
     */
    getName(String name){
    return "王五";
    }
    //私有函数
    String _getName3(){
      return "2";
    }
    
    //支持箭头函数写法
    main(){
      print(test1());
    }
    test()=> "zhujiang";
    String test1(){
      return "zhujiang";
    }
    
    //可选命名参数
    main() {
      print(add(a: 1, b: 3));
    }
    
    int add({int a = 1, int b = 0}) {
      return a + b; // 输出4
    }
    //可选位置参数
    int add2(int a,[int b = 2,int c = 3]) {
      return a + b;
    }
    print(add2(1));//3
    print(add2(1,2));//3
    print(add2(1,1,3));//2
    //必选在可选参数之前
    int add2([int b = 2,int c = 3],int a) { // 报错:Expected to find ')'.
      return a + b;
    }
    int add3(int c,{int a = 1, int b = 0}) {// 报错:Expected to find ')'.
      return a + b;
    }

    匿名函数

    • 分为有参匿名和无参数匿名
    JavaScript 复制代码
    //无参
    var printFun = () => print("**无参匿名函数**");
    
    //有参
    var printFun2 = (name) => print("**有参匿名函数 $name**");
    printFun2("sss");

    闭包

    • Dart内也有闭包的定义,这和JavaScript相似
    JavaScript 复制代码
    Function makeAddFunc(int x) {
      return (int y) => x + y;
    }
    var makeAddFun = makeAddFunc(11);
    
    void main(){
      print(makeAddFun(10));//输出21
    }

    词法作用域

    • Dart 的作用域是词法作用域,跟 JavaScript 一样,在写代码的时候就确定了。
    JavaScript 复制代码
    void test1(){
      var a = 2;
      void test2(){
        var b = 3;
        print(a);
      }
    }

    逻辑控制

    JavaScript 复制代码
      // for 循环
     for (var i = 0; i < 10; i++) {
        print(i);
      }
     print("=======for-in======");
    //for...in 循环
      var list = [1, 2, 3];
      var sets = <int>{1,2,3};
    
      for (var value in list) {
        print(value);
      }
      print("=======");
      for (var value in sets) {
        print(value);
      }
    
      print("===for-each====");
    //  for-each
      var collection = [1, 2, 3];
      collection.forEach((element) {
        print(element);
      });
      //遍历map
      var colorsMap = {
        1:"小明",
        2:"小红",
        3:"小张"
      };
      colorsMap.forEach((key,value) {
        print("$key-- $value");
      });
      print(colorsMap.toString());
      print(colorsMap.keys.toList());
      print(colorsMap.values.toList());
    
      colorsMap.keys.toList().forEach((element) {
        print("key $element");
      });
      colorsMap.values.toList().forEach((element) {
        print("values $element");
      });
    
    //  while 循环
      var while1 = 10;
      while (while1 > 0) {
        print(while1);
        while1--;
      }
      print("======do-while======");
      // do-while
      var i = 5;
      do {
        print(i);
        i--;
      } while (i > 0);
    
    //  do while 跟 while 的区别是即使不满足条件,do while 循环也会 do 一次;while 循环不会
    
    //  断言------assert
    //   assert(1 < 2); // 当表达式为false的时候,抛出异常
      // assert(1 > 2, '1>2 is wrong');//当表达式为false,抛出异常:  '1 > 2': 1>2 is wrong
    
      print("====异常-捕获=====");
    
    //  异常-捕获
    
      try {
        // throw Error(); // 输出:No specified type, handles all error Instance of 'Error'
        //抛出异常
        // throw Exception(); // 输出 this is Unknown exception Exception
        // ('this is exception error');
        // num i = 3 / 0;
        int i = 3~/0; // IntegerDivisionByZeroException
        print(i);
      } on Exception catch (e) { //1. 需要指定异常类型时使用on
        print('this is Unknown exception $e');
    
        rethrow;//3. 要部分处理异常,同时允许它继续抛出异常,请使用rethrow关键字,
      //  rethrow 会保留原异常的堆栈信息,而throw里面的堆栈信息会重新定位到最近的点
      // throw e;//这个堆栈信息打印就会只定位到88行。而rethrow会定位到真正错误的点,所以再次
        // 在try-catch里面抛出异常,最好使用rethrow
      } catch (e,s) {
        print('No specified type, handles all error $e');
        print('Stack trace:\n $s');
      }finally{
        print("finally "); // 一定会执行
      }
      //补充:如果有finally,finally代码块一定会执行,
      //所以finally代码块如果有return ,则会覆盖掉try/catch里面的return,
      //这点和java一样

    Dart面向对象

    类与对象

    • 构造函数
    • 命名构造函数
    • 常量构造函数
    • 工厂构造函数
    • Getter和Setter
    JavaScript 复制代码
    //dart中的构造函数
    class Point {
      num x;
      num y;
      Point(this.x, this.y);
      // String? name; // Declare instance variable name, initially null.
    // int _age = 0;
    //  2、命名式构造函数------使用初始化列表===>写法:类名.函数名():命名参数
    //   Person.origin(String name,int age):this.name = name,this._age = age;
    //  命名式构造函数的另一种写法
    //     Person.origin(String this.name,int this._age); 
    
    //  3、常量构造函数
    //  使用常量构造函数,要注意两点:一是要确保所有实例变量都是final;
    //  二、构造器前面要有const关键字,且不能要有函数载体
       final String? name; //
       final int _age; //
       const Person(this.name, this._age); 
       //    工厂构造函数
       static Person? instance;
      factory Person.getInstance(){
          if(instance == null){
            instance = Person("name", 31);
          }
          return instance as Person;
      }
    }

    get和set

    • 这个的好处是可以监听属性值的变换
    JavaScript 复制代码
    class Rect {
      int height;
      int width;
      Rect(this.width, this.height);
      // 手动指定 getter 的写法
      get area {
        return this.height * this.width;
      }
      // 手动指定 setter 的写法
      set h(int value) {
        print("当你调用 xx.h 时,会打印这段话,表示你已经被监听到了");
        this.height = value;
      }
    
      set w(int value) {
        this.width = value;
      }
    }
    
    void main(List<String> args) {
      var p = Rect(10, 20);
      print(p.area);// getter
      p.h = 100;// setter
      p.w = 100;
      print(p.area);
    }

    静态成员

    Dart泛型

    • 作用:把类型延迟到使用的时候指定
    dart 复制代码
    	show<T>(T a){
    	  print(a);
    	}
    	void main(List<String> args) {
    	 show<String>("hello");//"hello"
    	 //example2
    	 var p = My<int>();
    	  p.say(3);//3
    	}
    	class My<T>{
    	  say(T a){
    		print(a);
    	  }
    	}

    相关资料

    Dart官网教程
    Dart在线编辑器
    掘金中的Dart相关文章
    掘金中的Dart相关文章2:Dart从入门到放弃
    Dart关键字说明
    flutter1
    flutter2\

相关推荐
瓜子三百克4 小时前
七、性能优化
flutter·性能优化
恋猫de小郭12 小时前
Flutter Widget Preview 功能已合并到 master,提前在体验毛坯的预览支持
android·flutter·ios
小蜜蜂嗡嗡18 小时前
Android Studio flutter项目运行、打包时间太长
android·flutter·android studio
瓜子三百克1 天前
十、高级概念
flutter
帅次1 天前
Objective-C面向对象编程:类、对象、方法详解(保姆级教程)
flutter·macos·ios·objective-c·iphone·swift·safari
小蜜蜂嗡嗡1 天前
flutter flutter_vlc_player播放视频设置循环播放失效、初始化后获取不到视频宽高
flutter
孤鸿玉2 天前
[Flutter小技巧] Row中widget高度自适应的几种方法
flutter
bawomingtian1232 天前
FlutterView 源码解析
flutter
Zender Han2 天前
Flutter 进阶:实现带圆角的 CircularProgressIndicator
flutter