学习笔记,旨在于快速入门和学习Dart,其中可能会有理解错误,请指出,一起学习。
系列文章
2.1、Dart语言基础:变量、运算符
2.2、Dart语言基础:函数与闭包
2.3、Dart语言基础:面向对象
2.4、Dart语言基础:异步
2.5、Dart语言基础:库与包
...
一、概述
- 语法类似C语言,可以转译为JavaScript;
- 面向对象语言,属于强类型语言,支持可选类型;
参考:
dart英文官网
Dart 中文教程
dart-源码api
特性
重要概念
一切皆为对象
包括function函数、基础变量(int、float等)、null等;而且几乎所有类都继承于Object
基类,Null
除外。强类型语言,支持类型推导。
强类型指的是不能给变量赋值类型不匹配的值,如下:int类型的赋值字符串报错。
var age = 10; // 类型推导为int
age = "xxx"; // 给int类型的变量 赋值 字符串报错
print(age);
- 支持可选类型
空值安全type?
(类似于swift的可选类型),指的是变量可能为null。
int? aNullableInt = null;
如果变量确定一定有值,可以使用!
(如果为空,则会抛出异常)。
int x = nullableButNotNullInt!
- 字符串插值:
美元符号$varName 或者 ${varName}
void sayHelloworld(String name) {
print("$name say hello!"); //${name}
}
- 顶级入口
main
函数。
void main(List arguments) { ... }
- 定义任何类型的变量:
Object?、Object
或者 关键字dynamic
(在程序运行时才确定类型)。
二、基础
0、基本格式
代码语句,必须以 分号
;
结尾。代码注释:
单行语句// xxx
多行语句/* xxx */
类型安全检测:
Dart 的类型安全意味着不能使用if / assert
, 应该像下面这样,明确的进行值检查:
// 检查空字符串。
var fullName = '';
assert(fullName.isEmpty);
// 检查 0 值。
var hitPoints = 0;
assert(hitPoints <= 0);
// 检查 null 值。
var unicorn;
assert(unicorn == null);
// 检查 NaN 。
var iMeantToDoThis = 0 / 0;
assert(iMeantToDoThis.isNaN);
1、变量与常量
1.1、变量
Dart万物结尾对象,因此变量实际就是一个引用。
1.1.1、声明方式
方式一:明确指定类型
String name = 'hello';
方式二:不指定类型,关键字
var
官方推荐在函数内的本地变量尽量使用var声明。
var name = 'hello';
方式三:不指定类型,关键字
dynamic
在变量类型,不明确的情况下使用。
dynamic name = 'hello';
方式四:
?
明确指定可为空的变量
int? aNullableAge;
1.1.2、变量声明是否可以为空?
- 指定类型的变量,声明必须初始化,”不为空“,否则编译报错。
// Error: Non-nullable variable 'obj' must be assigned before it can be used.
Object obj;
print(obj);
// Error: Non-nullable variable 'nickName' must be assigned before it can be used.
String nickName;
print(nickName);
// Error: Non-nullable variable 'age' must be assigned before it can be used.
int age;
print(age);
- 可为空(
dynamic
、var
或者?
声明)的变量,初始化可以为空;
// 初始化可以不指定类型,值为null
dynamic nickName;
print(nickName);
var name;
print(name);
String? nickName1;
print(nickName1);
1.1.3、延迟变量,关键字late
(Dart 1.6新加)
- 定义一个允许延迟初始化的变量。
// late的特性:
Lazily initializing a variable.
Declaring a non-nullable variable that’s initialized after its declaration.
// late的使用场景
This lazy initialization is handy in a couple of cases:
1、The variable might not be needed, and initializing it is costly.
2、You’re initializing an instance variable, and its initializer needs access to this.
late String description;
void main() {
description = 'Feijoada!';
print(description);
}
- 如果
延迟变量
未被其他地方使用,对应语句不执行。
// 如果temperature没有被使用,则函数 _readThermometer 不会调用
late String temperature = _readThermometer();
1.2、常量
- 关键字
final
, 变量的值只能被设置一次。
最高级 final 变量或类变量在第一次使用时被初始化。
必须在构造函数体执行之前初始化 final 实例变量 —— 在变量声明中,参数构造函数中或构造函数的初始化列表中进行初始化。
// Error: Can't assign to the final variable 'name'.
final String name = 'hello';
name = 'new hello';
- 关键字
const
, 变量在编译时就已经固定。
如果 Const 变量是类级别的,需要标记为 static const。
实例变量可以是 final 类型但不能是 const 类型。
// Error: Can't assign to the const variable 'name'.
const String name = 'hello';
name = 'new hello';
1.2.1、变量 以及 变量本身 均不允许被修改
// Error: Can't assign to the const variable 'list'.
const list = [1, 2, 3];
list = [11, 12];
// Unsupported operation: Cannot modify an unmodifiable list
list[0] = 10;
print(list);
- 以下不会报错
// 此时,list推导的类型为不可变数组,修改字典值报错;
var list = const [1,2,3];
list[0] = 10; // 报错Unsupported operation: Cannot modify an unmodifiable list
// 但是变量list可以被重新初始化赋值
list = [1, 2, 3];
print(list);
list[0] = 10;
print(list);
3、内置类型
3.1、专有变量
3.2、数值类型,关键字num
,可以是int和double
num val = 1;
print(val); // 1
val += 0.5;
print(val); // 1.5
- 布尔值,关键字
false
和true
bool flag = false;
print(flag);
flag = true;
print(flag);
3.3、数组,关键字List
var list = [1, 2, 3];
list[0] = 0;
list.length;
// C语言,大括号
int arr1[3] = {1, 2, 3};
常用APIs:
void testListTypeDemo() {
var fruits = [];
print('isEmpty:${fruits.isEmpty}');
fruits.add('apples');
fruits.addAll(['pear', 'banana']);
print('原数组:$fruits');
print('first:${fruits.first}, last:${fruits.last}');
print('length:${fruits.length}');
print('indexOf: ${fruits.indexOf('banana')}');
print("contain:${fruits.contains('apples')}");
print("join:${fruits.join('、 ')}");
fruits.insert(0, 'watermalon');
print('原数组:$fruits');
print('range:${fruits.getRange(0, 2)}');
fruits.remove('apples');
fruits.removeAt(0);
print(fruits);
fruits.clear();
print(fruits);
var list = List.filled(8, 'name');
print(list);
var numbers = [1, 2, 3, 4, 5, 6, 7, 8];
print('原数组:$numbers');
numbers.sort((a, b) => a>b?a:b);
print('倒叙:$numbers');
}
- 展开运算符
spread operator (...) 和 null-aware spread operator (...?)
var list = [1, 2, 3];
var list2 = [0, ...list];
print(list2); // [0, 1, 2, 3]
var null_list;
var list3 = [0, ...?null_list]; // 可为空
print(list3); // [0]
-
collection if
和collection for
Dart also offers collection if and collection for, which you can use to build collections using conditionals (if) and repetition (for).
bool promoActive = true;
var nav = ['Home', 'Furniture', 'Plants', if (promoActive) 'Outlet'];
print(nav); // [Home, Furniture, Plants, Outlet]
var listOfInts = [1, 2, 3];
var listOfStrings = ['#0', for (var i in listOfInts) '#$i'];
print(listOfStrings); // [#0, #1, #2, #3]
3.4、集合,关键字Set
,(无序,大括号定义)
var halogens = {'fluorine', 'chlorine', 'bromine', 'iodine', 'astatine'};
var elements = {};
elements.add('fluorine');
elements.addAll(halogens);
- 在 Set 字面量前增加 const ,来创建一个编译时 Set 常量:
final constantSet = const {
'fluorine',
'chlorine',
'bromine',
'iodine',
'astatine',
};
3.5、字典,关键字Map
// Map
var gifts = {
// Key: Value
'first': 'partridge',
'second': 'turtledoves',
'fifth': 'golden rings'
};
3.6、标识符,Symbol
# label_1
# label_x
4、流程控制
-
if/else
(与C语言基本一样)
if (cond1) {
} else if (cond2) {
} else {
}
-
for
:与C语言基本类似,支持for-in,
for (int i=0; i<8; i++) {
print(i);
}
// for-in
for (var object in flybyObjects) {
print(object);
}
-
while / do-while
(与C语言基本一样)
while(1) {
}
do {
} while(1)
break/continue
(与C语言基本一样)在生产环境代码中
assert()
函数会被忽略,不会被调用。
在开发过程中,assert(condition)
会在非 true 的条件下抛出异常。
switch/case
- 使用
==
比较整数,字符串,或者编译时常量。 - 比较的对象必须都是同一个类的实例,并且不可以是子类, 类必须没有对
==
重写。 - 非空的
case
语句结尾需要跟一个 break 语句。空 case 语句, 允许程序以fall-through
的形式执行。
var command = 'CLOSED';
switch (command) {
case 'OPEN': //非空case,必须跟break
executeOpen();
break;
case 'CLOSED': // 空 case ,支持falls-through.
case 'NOW_CLOSED':
// Runs for both CLOSED and NOW_CLOSED.
executeNowClosed();
break;
}
- 支持
lable
var command = 'CLOSED';
switch (command) {
case 'CLOSED':
executeClosed();
continue nowClosed;
// Continues executing at the nowClosed label.
nowClosed:
case 'NOW_CLOSED':
// Runs for both CLOSED and NOW_CLOSED.
executeNowClosed();
break;
}
5、运算符
5.1、基本
- 除法:
~/ 和 /
assert(5 / 2 == 2.5); // 结果是双浮点型
assert(5 ~/ 2 == 2); // 结果是整型
- 支持自增自减:
++a、a++、--a、a--
5.2、空合运算符??
-
expr1 ?? expr2
如果 expr1 是 non-null, 返回 expr1 的值; 否则, 执行并返回 expr2 的值。
// 如果b为空时,将变量赋值给b,否则,b的值保持不变。
b ??= value;
5.3、类型判定运算符
-
as
将对象强制转换为特定类型。 -
is 和 is!
判断变量是不是某种类型。
5.4、级联运算符 ..
可以实现对同一个对像进行一系列的操作。
querySelector('#confirm') // 获取对象。
..text = 'Confirm' // 调用成员变量。
..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!'));