Dart 基础语法大全

412 阅读5分钟

1、变量和常量

1.1、变量

Dart语言中所有变量都是一个对象,每个对象都是一个类的实例。数字类型(numbers)、函数和 null 也是对象。所有对象都继承自 Object 类。

Dart中定义变量的方式有两种:

1、明确的指定变量的数据类型

String name;
int age;
double height;

2、使用 var / dynamic / Object 声明变量

var message1;
message1 = "str";
message1 = 19; //这行代码会报错
dynamic message2;
message2 = 1.78; 
message2 = "message2";//这行代码不会报错
print("${message2.length}");
Object message3;
message3 =  10;
message3 = "message3";
print("${message3.lenngth}"); //这句代码会报错

var与dynamic的区别

  • 1.var声明的变量一经赋值后,数据类型就已经确定,不可以接收其他的数据类型,所以message1 = 19这行代码报错
  • 2.dynamic声明的变量在第一次赋值后,可以继续接收其他的数据类型,所以message2 = "message2"这行代码不会报错

dynamic与Object的区别

  • 1.dynamic与Object声明的变量都可以再次接收其他类型的数据类型
  • 2.dynamic声明的变量可以使用变量运行时的属性跟方法,String类型的变量有length属性,所以可以使用,Object声明的变量只能使用Object本身的属性以及方法,Object类型本身不具备lehgth属性,所以print("${message3.lenngth}");这行代码会报错

1.2、final与const声明常量

const str = "sj";
final msg = "msg";

常量总结: 1.const与final 都用于声明常量,而且已经赋值都不可以被修改 2.const声明常量时,必须赋值明确的值,final声明的常量可以在运行时再赋值

2、数值型

Dart内置了一些类型

  • 1、Number:数值型
  • 2、String:字符串
  • 3、Boolean:布尔型
  • 4、List:列表
  • 5、Map:键值对
  • 6、Runes:符号字符
  • 7、Symbols:标示符

2.1、数值型

数值型分为整形int和浮点型double。可以用num、int、double声明。

num声明的变量加入的是int型,还可以被改为double型。但是反过来int声明的变量不能在赋值为double型。

比如正确的

num a = 10;
a = 10.0;

错误的

int a = 10;
a = 10.0;

我们看一下源码就可以理解了

abstract class int extends num {}
abstract class double extends num {}

2.2、数值型操作

  • 1、运算符:+、-、*、/、~/、%
    • ~/这个是dart中独有的,表示取整
  • 2、常用属性:isNaN、isEvent、isOdd等
    • sEvent:是否是偶数
    • isOdd:是否是奇数
  • 3、常用方法:round()、floor()、ceil()、toInt()、toDouble()、abs()
    • round():四舍五入
    • floor():不大于的最大整数
    • ceil():不小于的最小整数
    • abs():绝对值
int e = -20;
 print(e.abs());//绝对值 20
 double f = 10.5;
 print(f.round());//四舍五入  11
 print(f.floor());//不大于的最大整数 10;
 print(f.ceil());//不小于的最小整数 11
 print(f.toInt());//转成int 10;
 print(b.toDouble());//转double 12.0
 print(a.toInt());

3、字符串

3.1、字符串的创建

1、字符串定义

使用单引号或双引号

String a = "abcdefg";
String b = '12345';

2、创建多行字符串,保留内在格式

使用三个单引号或三个双引号 创建多行字符串,保留内在格式,如换行和缩进等,里面写什么输出就是什么。

  • 三个单引号
String e = '''asd
     fdsd
       fff
    
    ''';
  • 三个双引号
String f = """ 1
    2
    3
    4
    """;

3、使用r创建原始raw字符串(转义字符等特殊字符会输出出来,而不会自动被转义)

String str1=r'Hello \n  World'   

3.2、字符串常用属性

1、常规属性

String a20 = "aaaa";
String a21 = "";
  • 1、字符串长度
print(a20.length);//4
  • 2、是否为空
print(a20.isEmpty);//false 
print(a21.isEmpty);//true
  • 3、是否不为空
print(a20.isNotEmpty);//true 
print(a21.isNotEmpty);//false

2、字符串连接

String a = "abcdefg";
String b = '12345';
  • 1、使用+号连接
String c = a + b; //使用+号连接
print(c); //abcdefg12345
  • 2、使用相邻空格符号连接,必须是两个字符串 不能是变量
String d = 'aaa' 'bbb'; //使用相邻空格符号连接,必须是两个字符串 不能是变量 
print(d); //aaabbb

3、字符串模板,使用${} 将一个字符串变量/表达式嵌入到另一个字符串内

  • 1、变量
String a1 = "aa";
String b1 = "bb${a1}bb";
print(b1); //bbaabb
  • 2、表达式
String a1 = "aa";
String b2 = "bb${a1.toUpperCase()}bb";
print(b2); //bbAAbb

4、字符串与数字之间的转换

  • 1、字符串转int数值
int int1 = int.parse("33");
print(int1); //33
  • 2、字符串转double数值
double d1 = double.parse("3.33");
print(d1); //3.33
  • 3、数值转字符串
print(33.toString());
print(3.34.toString());
  • 4、数值转字符串保留精度
print(3.12345.toStringAsFixed(3)); //保留精度 3.123

5、字符串切割

String a2 = "aaabbb";
  • 1、含头不含尾
print(a2.substring(0, 2)); //aa 含头不含尾
  • 2、从指定index至末尾
print(a2.substring(3)); //bbb 从指定index至末尾
  • 3、使用,分割,返回的是一个数组
String a5 = "a,d,d d,c,,"; 
List<String> a6 = a5.split(",");//使用,分割,返回的是一个数组
print(a6.length); //6 
print(a6);//[a, d, d d, c, , ]
  • 4、正则匹配,拆分字符串
String strB = "abba";
print(strB.split(new RegExp(r"b*")));
  • 5、查询,并替换
String a8 = "a b,c";
    String a7 = a8.splitMapJoin(",",//查询“,”,用onMatch的返回值替换“,”用onNonMatch的返回值替换其他
        onMatch: (Match match) {
          return "a";
        }, onNonMatch: (String nonMatch) {
          return "b";
        });
    print(a7);//bab    a b,c  =>   bab

6、字符串判断 是否包含或以xxx开始结束等

String a3 = "aaabbbccc";
  • 1、是否以‘xxx’开头
print(a3.startsWith("aa")); //true
print(a3.startsWith("aa", 3)); //false 从index=3开始判断
  • 2、是否以‘xxx’结尾
print(a3.endsWith("c")); //true
  • 3、是否包含‘xxx’
print(a3.contains("ab")); //true
print(a3.contains("ac")); //false
  • 4、从某处开始是否包含‘xxx’
print(a3.contains("ab", 3)); //false 从index=3开始判断

7、字符串替换

String a4 = "abcdeab";
  • 替换全部符合条件的
print(a4.replaceAll("ab","cc"));//cccdecc 替换全部符合条件的
  • 只替换第一个符合条件的
print(a4.replaceFirst("ab", "dd"));//ddcdeab 只替换第一个符合条件的
  • 从index=3开始 替换第一个符合条件的
print(a4.replaceFirst("ab", "dd",3));//abcdedd 从index=3开始 替换第一个符合条件的
  • 范围替换 从0-3 含0不含3
print(a4.replaceRange(1, 3, "z"));// 范围替换 从0-3 含0不含3
  • 用方法返回值替换指定的字符串
print(a4.replaceAllMapped("c", (Match match){//abyydeab 用方法返回值替换指定的字符串
  return "yy";
}));
  • 从index=2开始 用方法返回值替换指定的字符串
//abcdea333 从index=2开始 用方法返回值替换指定的字符串
print(a4.replaceFirstMapped("b", (Match match){
  return "333";
},2));

8、字符串查找

String a9 = "aababcc1bc23";
  • 获取指定字符出现的位置
String str = 'Dartisans';
print(str.indexOf('art'));
print(str.indexOf(new RegExp(r'[A-Z][a-z]')));
print(str.lastIndexOf('a'));
print(str.lastIndexOf(new RegExp(r'a(r|n)')));
  • 第一个符合条件的index
print(a9.indexOf("ab"));//1 
  • 从index=xx开始往后找
print(a9.indexOf("ab",2));//3index=2开始往后找
print(a9.indexOf("ab",4));//-1index=4开始往后找,找不到返回-1
  • 从后往前找 返回第一个符合条件的index
print(a9.lastIndexOf("bc"));//8 从后往前找 返回第一个符合条件的index
  • 从后往前找 从index=xxx开始找 返回第一个符合条件的index 找不到返回-1
//-1 从后往前找 从index=3开始找 返回第一个符合条件的index 找不到返回-1
print(a9.lastIndexOf("bc",3));

//4 从后往前找 从index=7开始找 返回第一个符合条件的index

print(a9.lastIndexOf("bc",7));

9、去除空格

String a11 = " aab bcc ";
print(a11);// aab bcc
  • 去除左右两边空格
print(a11.trim());//aab bcc 去除左右两边空格
  • 去除右边空格
print(a11.trimRight());// aab bcc 去除右边空格
  • 去除左边空格
print(a11.trimLeft());// aab bcc //去除左边空格

10、补齐长度 剩余位使用指定字符串替换

String a13 = "111";
  • 剩余3个位 默认使用""补齐
print(a13.padLeft(6));// 111 剩余3个位 默认使用""补齐
  • 剩余3个位 指定使用"c
print(a13.padRight(6,"c")); //111ccc 剩余3个位 指定使用"c"
  • 剩余3个位 每个位指定使用"dd" 替换后总长度不是6
print(a13.padRight(6,"dd")); //111dddddd 剩余3个位 每个位指定使用"dd" 替换后总长度不是6
  • 如果指定长度小于原字符串长度 返回原字符串
print(a13.padLeft(2,"e"));//111 如果指定长度小于原字符串长度 返回原字符串

11、字符串先后比较

String a12 = "bbcc";
print(a12.compareTo("aaa"));//1 在ascii码中 b>a
print(a12.compareTo("bbcc"));//0
print(a12.compareTo("dd"));//-1 在ascii码中 b<d

12、字符串Unicode编码

  • codeUnitAt(方法返回给定索引处的16位UTF-16代码单元) 
    • 参数  index- 表示字符串中的字符索引。
    • 返回值  返回一个数字值。
String.codeUnitAt(int index)
void main() { 
   var res = "Good Day"; 
   print("Code Unit of index 0 (G): ${res.codeUnitAt(0)}");  
}
Code Unit of index 0 (G): 71
  • codeUnits(属性返回给定字符串的UTF-16代码单元列表)
String.codeUnits
void main() { String str = "Hello"; print(str.codeUnits); }
 
[72, 101, 108, 108, 111]

13、字符串运算符(+、==、[])

  • +:加好运算符,字符串拼接功能
String a = 'abc';
String b = 'cbd';
print(a+b);//abccbd
  • ==:等号运算符,比较两个字符串是否相同
String a = 'abc';
String b = '2';
if(a == b){
 print('true');
}else{
 print('false');
}//返回false
  • []:取值运算符,取出字符串索引位指向的单个字符
String a = 'abc';
String b = '2'; print(a[1]);//b

4、List

1、声明

    var list1 = List();// 不限定长度,不限定类型,可添加任意类型的数据
    List list2 = List();// 不限定长度,不限定类型,可添加任意类型的数据
    List list3 = List(2);//限定了长度为2  越界会报错,不限定类型,可添加任意类型的数据

    list1.add(1);
    list1.add('aaa');
    list1.add(true);
    print(list1);//[1, abc, true]
    var list4 = [1,2,3];//初始就赋值了,限定了长度,限定了类型,只能是int
    var list5 = [2,'3',true];//初始就赋值了,限定了长度,未限定类型,任意位置可用任意类型替换
    List list6 = ['a',2,'b',false];//初始就赋值了,限定了长度,未限定类型,任意位置可用任意类型替换
    list5[1] = 2;
    list5[2] = 'aa';
    print(list5);//[2, 2, aa]
    var list33 = <String>["a","b"];
    List<String> list7 = ['a','b','3'];
    List<String> list8 = new List(2);
    list8[0]=('aaa');
    print(list8);//[aaa, null]

2、常用属性

    List<String> list13 = List();
    list13.add('aaa');
    list13.add('bbb');
    list13.add('ccc');
    print(list13.length);//3    长度
    print(list13.isEmpty);//false      是否为空
    print(list13.isNotEmpty);//true     是否不为空
    print(list13.reversed);//(ccc, bbb, aaa)      返回一个List的倒序排列的Iterable  不改变原List
    print(list13.first);//aaa    第一个元素
    print(list13.last);//ccc    最后一个元素

3、常用方法

1、增

  • 1、add() 添加一个元素到List末尾
    List<String> list9 = List();
    list9.add('aaa');
    list9.add('bbb');
    print(list9);//[aaa, bbb]
  • 2、addAll() 两个List合并
    List<String> list10 = List();
    list10.add('aaa');
    list10.add('bbb');
    List<String> list11 = List();
    list11.add('ccc');
    list11.add('ddd');
    list11.addAll(list10);
    print(list11);//[ccc, ddd, aaa, bbb]
  • 3、insert(index,element) 在指定index处插入值
    List<int> list21 = List();
    list21.add(0);
    list21.add(1);
    list21.add(2);
    list21.add(3);
    print(list21);//[0, 1, 2, 3]
    list21.insert(1, 5);  //指定索引位置 插入值,其余顺延
    print(list21);// [0, 5, 1, 2, 3]
  • 4、insertAll(index,list) 在指定index处插入list 其余顺延
    List<int> list25 = List();
    list25.add(0);
    list25.add(1);
    list25.add(2);
    list25.add(3);
    print(list25);//[0, 1, 2, 3]
    list25.insertAll(1, [5,6,7]);
    print(list25);//[0, 5, 6, 7, 1, 2, 3]
  • 5、followedBy(list) 将自身和参数内list合成一个List
List<int> list = [1,2,3];
Iterable<int> list1 = list.followedBy([4,5]);
print(list1);//(1, 2, 3, 4, 5)

2、删

  • remove(obj) 删除具体的元素
  • removeAt(index) 删除索引位置元素
  • removeLast()删除末尾元素
  • removeRange(start,end) 范围删除
  • removeWhere() 根据条件删除:
  • clear() 清空数组
void removeWhere(bool test(E element));

List<String> list = List();
  list.add("aa");
  list.add("bb");
  list.add("cc");
  list.add("dd");
  list.add("ee");
  list.add("ff");
  //根据条件 筛选,这里表示删除元素值为dd
  list.removeWhere((element){ return element=='dd';}); 
  print(list);//[aa, bb, cc, ee, ff]
  //条件只有一个表达式时,可以用箭头函数简化写法
  list.removeWhere((element)=> element=='cc');

3、改

  • 1、修改指定index位置的值
var list = [2,'3',true];
list[1] = 2;
  • 2、setRange(startIndex,endIndex,list) 范围修改List的值
List<String> list = List();
    list.add('aaa');
    list.add('bbb');
    list.add('ccc');
    list.add('ddd');
    print(list);// [aaa, bbb, ccc, ddd]
    List<String> list1 = List();
    list1.add("111");
    list1.add("222");
    list1.add("333");
    list1.add("444");
    list1.add("555");
    list1.add("666");
    list.setRange(0,3, list1);
    //范围修改,从list1取出0 1 2位置的值,修改list对应0 1 2位置的值,0-3含头不含尾,start和end相同,则不变。
    //start和end任何一个超出list list1的角标 则报错。
    print(list);//[111, 222, ccc, ddd]
  • 3、replaceRange(start,end,list)范围替换 含头不含尾
List<String> list = List();
list.add('aaa');
list.add('bbb');
list.add('ccc');
list.add('ddd');
print(list);// [aaa, bbb, ccc, ddd]
list.replaceRange(0,2,["1","2","3"]);
print(list);//[1, 2, 3, ccc, ddd]
  • 4、fillRange(start,end,value) 从start-end 每个元素用value替换
List<String> list = List();
    list.add('aaa');
    list.add('bbb');
    list.add('ccc');
    list.add('ddd');
    print(list);// [aaa, bbb, ccc, ddd]
    list.fillRange(0,2,"1");
    print(list);//[1, 1, ccc, ddd]
  • 5、retainWhere(()=>(bool)) 根据条件筛选元素
List<String> list = List();
    list.add('aaa');
    list.add('bbb');
    list.add('ccc');
    list.add('ddd');
    print(list);// [aaa, bbb, ccc, ddd]
    list.retainWhere((element)=>(element=="aaa"));
    print(list);//[aaa]
  • 6、setAll(index,list) 从index开始,使用list内的元素逐个替换本list中的元素
List<String> list = List();
    list.add('aaa');
    list.add('bbb');
    list.add('ccc');
    list.add('ddd');
    print(list);// [aaa, bbb, ccc, ddd]
    list.setAll(1,["1","2"]);
    print(list);//[aaa, 1, 2, ddd]

4、查

  • 1、indexOf(element,[start]) 查找指定元素在list中的索引
  • 2、lastIndexOf(obj,index) 从后往前查找,返回第一个的index
  • 3、elementAt(index) 获取指定索引位置的元素
  • 4、any((element)=>(bool)) 判断List中是否有任意一个元素符合给定的参数
List<String> list = List();
    list.add('aaa');
    list.add('bbb');
    list.add('ccc');
    list.add('ddd');
   //判断list元素中是否有任何一个元素满足给定的条件,如果满足返回true 否则false
    bool result = list.any((element)=>(element=="aa"));
    print(result);//false
  • 5、every((element)=>(bool)) 判断List中是否每个元素都符合参数函数
 List<int> list1 = [1, 2, 3, 4, 5];
  //是否每个元素都符合条件   都符合返回true  否则返回false
   bool result1 = list1.every((element)=>(element%2==0));
  • 6、contains(obj) List中是否存在给定的obj
  • 7、firstWhere((element)=>(bool)) 返回第一个满足条件的元素(不是元素的index)
List<int> list1 = [1, 2, 3, 4, 5];
   //返回满足条件的第一个元素
   int result = list1.firstWhere((ele)=>(ele>3));
   print(result);//4
  • 8、lastIndexWhere((e)=>(bool)) 从后向前找 返回第一个满足条件的元素的index
  • 9、lastWhere((e)=>(bool)) 从后往前找,返回第一个满足条件的元素的值(不是index)
  • 10、forEach() List遍历每个元素
List<String> list = List();
    list.add('aaa');
    list.add('bbb');
    list.add('ccc');
    list.add('ddd');
    //遍历每个元素  此时不可add或remove  否则报错 但可以修改元素值
    list.forEach((ele){
      print(ele);
    });
  
  for(var x in list){
    print(x);
  }
  • 11、map() 遍历现有List的每个元素,并做处理,返回一个新的Iterable
List<int> list = [1,2,3];
  Iterable<String> list1 = list.map((ele)=>(ele>2?"a":"b"));
  print(list1);//(b, b, a)
  • 12、fold(initValue,(preValue,element)=>()); 根据现有的List和给定的initValue,指定一个参数函数规则,对List每个元素做操作,并将结果返回。
List<int> list = [1,2,3];
  int result = list.fold(2,(a,ele)=>(a*ele));
  print(result);//12
  • 13、reduce((a,b)=>(某种操作)) 用指定的方法对元素做连续操作,将结果返回
List<int> list = [1,2,3];
  int result = list.reduce((a,b)=>(a+b));
  print(result);//6
  • 14、skip
    • skip(count)越过count个元素后,开始返回list的Iterable
    • skipWhile((e)=>(bool)) 根据参数函数,找到第一个不符合条件的元素,然后将其及其后的元素返回
List<int> list = [3, 4, 5, 2, 1];
  //越过count个元素后,开始返回list的Iterable
  Iterable<int> result = list.skip(2);
  print(result);//(5, 2, 1)
  
  //从第一个元素开始,逐个判断是否符合参数函数,直至第一个不符合的元素,将其及其后面的元素返回
  Iterable<int> result1 = list.skipWhile((e)=>(e>2));
  print(result1.toList());//[2, 1]
  • 15、take
  • take(count) 从0开始取count个元素,并返回结果
  • takeWhile((e)=>(bool)) 从0开始取,直至第一个不符合函数的元素,将其前面的元素都返回。
List<int> list = [3, 4, 1, 2, 5];
  //从0开始取2个元素  并返回
   Iterable<int> result = list.take(2);
   print(result);//(3, 4)
  
   //从第一个元素开始,逐个判断是否符合参数函数,直至第一个不符合的元素,将其前面元素都返回
   Iterable<int> result1 = list.takeWhile((e)=>(e>2));
   print(result1);//(3, 4)
  • 16、where
1、where((e)=>(bool) 根据指定参数函数筛选每个元素,符合条件的元素组成一个新的Iterable

List<int> list = [3, 4, 1, 2, 5,2,3,6];
    //根据参数函数筛选
    Iterable<int> result = list.where((e)=>(e>2));
    print(result);//(3, 4, 5, 3, 6)

2singleWhere((e)=>(bool>) 找到那唯一满足条件的元素
 
 List<int> list = [3, 4, 1, 2, 5];
  //找到那唯一满足条件的元素,如果没有满足条件的元素或有多个元素满足条件,就返回orElse方法的返回值,如果没有传入orElse则报错。
    int result = list.singleWhere((e)=>(e>4),orElse: ()=>(10));
   print(result);//5
 
 
3whereType() 从无指定泛型的List中,筛选出指定类型的数据。 
List list = [3, 4, "a",true,"b",5,false];
    //从混合类型的List中,筛选出指定类型的数据
    Iterable<int> result = list.whereType();
  
    print(result);//(3, 4, 5)
    Iterable<String> result1 = list.whereType();
    print(result1);//(a, b)
    Iterable<bool> result2 = list.whereType();
    print(result);//(true, false)


  • 17、expand() 根据现有的List,指定一个规则,生成一个新的List
 List<int> list = [1, 2, 3, 4, 5];
    //通过对元素操作,返回一组指定规则的新的集合
    Iterable<int> result = list.expand((element)=>([element+1,element+2]));
    print(result);//(2, 3, 3, 4, 4, 5, 5, 6, 6, 7)
  • 18、toSet() 将List转为Set 去除后面重复的元素
List<int> list = [3, 4, 1, 2, 5,2,3,6];
    //将list转为set,将后面重复的都去掉
    Set<int> result = list.toSet();
    print(result);//{3, 4, 1, 2, 5, 6}
  • 19、asMap() 将list转为map
List<String> list = List();
    list.add("aaa");
    list.add("bbb");
    list.add("ccc");
    list.add("ddd");
    list.add("eee");
   print(list);// [aaa, bbb, ccc, ddd, eee]
    Map<int,String> map = list.asMap();//list转为map  key为index  value为list的值
   print(map);//{0: aaa, 1: bbb, 2: ccc, 3: ddd, 4: eee}
 
  • 20、sort() List自身排序
List<int> list20 = List();
    list20.add(2);
    list20.add(3);
    list20.add(1);
    list20.add(0);
//    print(list20);//[2, 3, 1, 0]
    list20.sort((a,b)=>(a>b?1:-1));//自身排序  修改本身的list
//    print(list20);//[0, 1, 2, 3]
  • 21、sublist(start,[end]) 从指定index 截取list
List<int> list21 = List();
    list21.add(0);
    list21.add(1);
    list21.add(2);
    list21.add(3);
    print(list21);//[0, 1, 2, 3]
    list21.insert(1, 5);  //指定索引位置 插入值,其余顺延
    print(list21);// [0, 5, 1, 2, 3]
    List<int> list22 = list21.sublist(1);//从指定索引截取List
    List<int> list23 = list21.sublist(1,3);//从指定索引截取List  含头不含尾
    print(list22);//[5, 1, 2, 3]
    print(list23);//[5, 1]
  • 22、getRange(start,end) 从list中截取start-end范围内的数据
List<int> list28 = List();
    list28.add(0);
    list28.add(1);
    list28.add(2);
    list28.add(3);
    list28.add(4);
    list28.add(5);
    list28.add(6);
    list28.add(7);
//    print(list28);//[0, 1, 2, 3, 4, 5, 6, 7]
    Iterable<int> list29 = list28.getRange(2, 5);//含头不含尾,从2开始到5(不含)结束的一个Iterable
//    print(list29);//(2, 3, 4)
  • 23、join("-") 用指定的字符将List中每个元素都连接起来,返回一个字符串
    List<int> list50 = [3, 4, 1, 2, 5];
    String result24 = list50.join("-");//用指定的字符将每个元素都连接起来,返回一个字符串
//    print(result24);//3-4-1-2-5

5、Map

在Dart中,Map是以key-value形式存储,键和值都可以是任何类型的对象,每个键只能出现一次

1、声明

  • 1、通过直接声明的方式创建一个Map
Map game = {"game":"Switch","company":"任天堂"};
  • 2、创建一个不可变的Map,需要在Map前面加一个const
Map game = const{"game":"Switch","company":"任天堂"};
  • 3、构造方式声明
Map game = new Map();
game['name'] = '任天堂';

2、属性

print(citys.length); //长度
  print(citys.isEmpty); //是否为空
  print(citys.isNotEmpty); //是否不为空
  print(citys.keys);// key的集合
  print(citys.values);//value的集合
  //(MapEntry(cityname: 北京), MapEntry(cityid: 10001),   MapEntry(1: 1))
  print(citys.entries);// map迭代的键值对集合

3、方法

  citys.update('1', (value)=>(value+'23')); //存在的值可以直接修改,不存在的值就直接报错
  print(citys);
  //key不存在,因为用ifAbsent参数, 返回ifAbsent函数的值,并添加到map中
  citys.update('2', (value)=>(value+'34'), ifAbsent: ()=>('123'));
  print(citys);

  //updateAll根据参数函数的规则,批量修改app
  Map<String,int> map1 = {'a':1,"b":2,"c":3}; //指定泛型初始化map
  map1.updateAll((k,v){
    return v*2;
  });
  print(map1);

  map1.updateAll((k,v){
    if(k=='a'){return 100;}
    if(k=='b'){return 200;}
    return v*10;
  });
  print(map1);

  //删除一个key remove  
  map1.remove('a');
  print(map1);
  //根据条件批量删除
  Map<String,int> map10 = {"a":1,"b":2,"c":3,"d":4,"e":5};
  map10.removeWhere((k,v)=>(v>3)); //删掉符号参数函数keyvalue对
  print(map10); //{a: 1, b: 2, c: 3}
  
  //是否包含
  map10.containsKey('a'); //是否包含key
  map10.containsValue(1); //是否包含value

4、遍历

names.forEach((k,v){  //forEach 遍历
  print('遍历 $k , $v');
});
names.map((k,v){    //map方法放回一个新的数组
  return MapEntry(v, k);
});
print('map: $names');

5、清空

//清空map
  names.clear();
  print('names $names');

6、添加addall

Map<String,int> map11 = {'a':1,'b':2,'c':3};
  Map<String,int> map12 = {'d':3,'e':5,'f':5,'c':10};
  //addAll 整体合并另一个map,泛型要一致 key相同时value值后者覆盖前者.前者不存在就添加进来
  map11.addAll(map12);
  print(map11);
  //addEntries 合并两个map,如果key有重复,并合并的map的value覆盖前者
  map11.addEntries(map12.entries);
  print(map11);
  //putlfAbsent() 存在就获取值,不存在则添加到map,然后返回值
  int result= map12.putIfAbsent('c', ()=>(100)); //存在
  print(result); //10
  int result2 = map12.putIfAbsent('t', ()=>1000); //不存在
  print(result2);
  print(map12); //map中也会跟着添加进去

7、cast 泛型类型提升为其父祖类

//cast() 泛型类型提升为其父祖类
  Map<String,int> map21 = {"a":1,"b":2,"c":3};
  Map<Object,Object> map22 = map21.cast();
  map22["d"]=33;
  //    print(map22);//{a: 1, b: 2, c: 3, d: 33}

6、dynamic&Object

dynamic: [daɪˈnæmɪk] 动态的;动力的;动力学的;有活力的

基础

在Dart里面,一切皆对象,而且这些对象的父类都是Object。 当没有明确类型的时候,编译的时候回根据值明确类型

var name1 = "abc";
Object name2 = "def";
dynamic name3 = "hij";

以上写法都没有问题,但是Dart不建议我们这么做。在实际开发过程中,我么么应该尽量为变量确定一个类型,这样可以提高安全性,加快运行速度。

如果不指定类型,debug模式下类型会是动态的。

使用dynamic时,则告诉编译器,我们不用做类型检测,并且知道自己在做什么。如果我们调用了一个不存在的方法时,回执行noSuchMethod()方法。 在默认情况下(Object里实现)它会抛出NoSuchMethodError

dynamic,var,object三者的区别

void main()//dynamic,var,object三者的区别
{
  //dynamic
  dynamic x = 'hello';//编译时不会揣测数据类型,但是运行时会推断
  print(x.runtimeType);//String
  print(x);
  //但是这样的坏处就是会让dart的语法检查失效,所以有可能会造成混乱而不报错
  //所以不要直接使用dynamic
  x = 123;
  print(x.runtimeType);//int,说明类型是可变的
  print(x);
 
  //var
  var a = 'hello';
  print(a.runtimeType);
  print(a);
  //a = 123;//会报错
  a = '123';
  print(a);
 
  //Object
  Object w = 1;
  print(w.runtimeType);
  print(w);
  //不能调用Object不存在的方法
  
}

dynamic与Object的最大的区别在于静态类型检查上

7、运算符

我们都知道计算机高级语言都有大同小异的运算符,那接下来让我们来看看Dart有哪些运算符。

使用运算符时,可以创建表达式。 以下是运算符表达式的一些示例:

a++
a + b
a = b
a == b
c ? a : b
a is T

在运算符表中,每个运算符的优先级高于其后面行中的运算符。 例如,运算符%的优先级高于运算符==,它的优先级高于逻辑与运算符&&。 该优先级意味着以下两行代码执行相同的方式:

// Parentheses improve readability.
if ((n % i == 0) && (d % i == 0)) ...
// Harder to read, but equivalent.
if (n % i == 0 && d % i == 0) ...

算术运算符

Dart支持通常的算术运算符,如下表所示。

要测试两个对象x和y是否表示相同的东西,请使用==运算符。 (在极少数情况下,你需要知道两个对象是否完全相同,请使用identical()函数。)以下是==运算符的工作原理:

  • 果x或y为null,则如果两者都为null则返回true;如果只有一个为null,则返回false。
  • 回调用方法 x.==(y)的结果。 (没错,运算符如==是在第一个操作数上调用的方法。你甚至可以覆盖许多运算符,包括 == )
assert(2 == 2);
assert(2 != 3);
assert(3 > 2);
assert(2 < 3);
assert(3 >= 3);
assert(2 <= 3);

运算符

as,is,is! 运算符在运行时检查类型很方便。

当 obj是指定接口T的实现,那么obj is T的结果是 true. 举个例子, obj is Object永远是true。 使用as运算符将对象强制转换为特定类型。 通常,你应该为了缩短一个对象使用之前,对该对象做is测试。

if (emp is Person) {
  // Type check
  emp.firstName = 'Bob';
}

你可以使用as运算符缩短代码:

(emp as Person).firstName = 'Bob';

注意:这两段代码不是相同的,如果emp是null 或者不是一个Person, 那么第一个例子(用is的)不会做任何事;第二个例子(用as的)会抛出一个异常。

赋值运算符

如你所见,你可以使用=运算符指定值。 要仅在变量为null时赋值,请使用??=运算符。

// Assign value to a
a = value;
// Assign value to b if b is null; otherwise, b stays the same
// b为null时才会赋值,不为null不会改变b的值
b ??= value;

复合赋值运算符(如+=)将运算与赋值组合在一起。

逻辑运算符

你可以使用逻辑运算符反转或组合布尔表达式。

if (!done && (col == 0 || col == 3)) {
  // ...Do something...
}

条件表达式

Dart有两个运算符,可以让你简单的得出需要if-else语句表达式的结果: condition? expr1 : expr2 如果condition为true,则计算expr1(并返回其值); 否则,计算并返回expr2的值。 expr1 ?? expr2 如果expr1为非null,则返回其值; 否则,计算并返回expr2的值。

当你需要根据布尔表达式赋值时,请考虑使用?:

var visibility = isPublic ? 'public' : 'private';

如果布尔表达式测试null,考虑使用??

String playerName(String name) => name ?? 'Guest';

级联符号(..)

Cascades(..)允许你对同一对象进行一系列操作。 除了函数调用,你还可以访问同一对象上的字段。 这通常可以为您节省创建临时变量的步骤,并允许你编写更多流畅的代码。

querySelector('#confirm') // Get an object.
  ..text = 'Confirm' // Use its members.
  ..classes.add('important')
  ..onClick.listen((e) => window.alert('Confirmed!'));

第一个方法调用querySelector()返回一个选择器对象。 级联表示法后面的代码对此选择器对象进行操作,忽略可能返回的任何后续值。

前面的例子等同于:

var button = querySelector('#confirm');
button.text = 'Confirm';
button.classes.add('important');
button.onClick.listen((e) => window.alert('Confirmed!'));

你也可以嵌套级联:

final addressBook = (AddressBookBuilder()
      ..name = 'jenny'
      ..email = 'jenny@example.com'
      ..phone = (PhoneNumberBuilder()
            ..number = '415-555-0100'
            ..label = 'home')
          .build())
    .build();

小心在返回实际对象的函数上构造级联。 例如,以下失败代码:

var sb = StringBuffer();
sb.write('foo')
  ..write('bar'); // Error: method 'write' isn't defined for 'void'.

调用sb.write()返回了 void,然而你不能在void 上构造一个级联

注意:严格来说,级联的“双点”符号不是运算符。 它只是Dart语法的一部分。

8、函数

Dart是一门面向对象的语言,所以函数也是对象,并且函数的类型是Function

1、函数的基本使用

函数的参数可以分成两类: 必须参数和可选参数

可选参数可以分为 命名可选参数 和 位置可选参数

定义方式:

命名可选参数: {param1, param2, ...}
位置可选参数: [param1, param2, ...]

1、main函数

每个应用程序都必须有一个顶层的main函数。它是一个应用程序的切入口。改main函数返回void并具有List的可选参数

void main() {
  runApp(MyApp());
}

2、可选参数

可选的命名参数,即使不传递这些参数也是可以的。 在定义函数时,使用{param1,parqm2,...}指定命名参数。

void userSettings({int age,String name}){
  if(age != null) {
    print('my age is ${age}');
  } 
  if(name != null) {
    print('my name is ${name}');
  } 
}

上面函数中,我们可以传递age、name这两个参数,绘制其一,或者一个都不传递

3、必传参数

有时候,我们在调用函数的时候,必须传入一些参数,这个时候就用到了@required来修饰。使用@required有利于静态代码分析器进行检查

void userSettings({@required int age,String name}){
  if(age != null) {
    print('my age is ${age}');
  }
  if(name != null) {
    print('my name is ${name}');
  }
}

4、可选的位置参数

使用[]把目标标记为可选的位置参数

 void userSettings(int age, String name, [String interests]){
  if(age != null) {
    print('my age is ${age}');
  }
  if(name != null) {
    print('my name is ${name}');
  }
  if(interests != null){
    print('兴趣是${interests}');
  }
}

5、默认参数

默认值是编译时常量,在函数的参数后面使用 = 为参数赋值

  • 参数可以有默认值, 在不传入的情况下, 使用默认值
  • 注意, 只有可选参数才可以有默认值, 必须参数不能有默认值
void userSettings(int age, String name, [String interests,String sex = "男"]){
  if(age != null) {
    print('my age is ${age}');
  }
  if(name != null) {
    print('my name is ${name}');
  }
  if(interests != null){
    print('兴趣是${interests}');
  }
  if(sex != null){
    print('性别${sex}');
  }
}

6、函数作为参数

executeFunction(fn, [args]) {
  if (fn != null) {
    return fn(args);
  }
}

7、函数作为变量

var say = (name){
	pring(name);
}
say('小明');

2、箭头函数

List l1 = [1, 2];

l1.forEach((item) {
    print(item);
});

l1.forEach((item) => print(item));

箭头函数只能有一行,可以省略大括号 在 map 方法中使用箭头函数:

var l2 = l1.map((item) {
    return item % 2 == 0 ? item * 2 : item;
  });
  print(l2.toList());

  var l3 = l1.map((item) => item % 2 == 0 ? item * 2 : item);
  print(l3);

3、匿名函数

某些情况下,给函数命名太麻烦了,我们可以使用没有名字的函数,这种函数可以被称之为匿名函数( anonymous function),也可以叫lambda或者closure。

main(List<String> args) {
  // 1.定义数组
  var movies = ['盗梦空间', '星际穿越', '少年派', '大话西游'];

  // 2.使用forEach遍历: 有名字的函数
  printElement(item) {
    print(item);
  }
  movies.forEach(printElement);

  // 3.使用forEach遍历: 匿名函数
  movies.forEach((item) {
    print(item);
  });
  movies.forEach((item) => print(item));
}

4、立即执行函数

 // 立即执行方法
  ((name) {
    print('my name is ${name}');
  })('postbird');

5、闭包

 // 闭包
  Function getA() {
    int a = 0;
    return () {
      a++;
      print(a);
    };
  }

  Function b = getA();
  b();
  b();