语法篇
九种内置类型
Numbers (int, double)
Dart 支持两种 Number 类型:int(整数值) double(双精度浮点数字)
整型支持传统的位移操作,移位(<<、>> 和 >>>)、补码 (~)、按位与 (&)、按位或 (|) 以及按位异或 (^)
assert((3 << 1) == 6); // 0011 << 1 == 0110
assert((3 | 4) == 7); // 0011 | 0100 == 0111
assert((3 & 4) == 0); // 0011 & 0100 == 0000
Strings (String)
使用三个单引号或者三个双引号也能创建多行字符串
在字符串中,请以 ${表达式} 的形式使用表达式,如果表达式是一个标识符(var s = 'string'),可以省略掉 {}
可以使用 + 运算符或并列放置多个字符串来连接字符串
使用三个单引号或者三个双引号也能创建多行字符串
在字符串前加上 r 作为前缀创建 “raw” 字符串, 则不会被转义
Booleans (bool)
Lists (也被称为 arrays)
var list = [1, 2, 3];
在 List 字面量前添加 const 关键字会创建一个编译时常量
var constantList = const [1, 2, 3];
// constantList[1] = 1; // This line will cause an error.
扩展操作符(...)和 空感知扩展操作符(...?)
var list = [1, 2, 3];
var list2 = [0, ...list];
assert(list2.length == 4);
var list2 = [0, ...?list]; // 如果扩展操作符右边可能为 null
assert(list2.length == 1);
list 的骚操作写法
var nav = ['Home', 'Furniture', 'Plants', if (promoActive) 'Outlet'];
var listOfInts = [1, 2, 3];
var listOfStrings = ['#0', for (var i in listOfInts) '#$i'];
assert(listOfStrings[1] == '#1');
Sets (Set)
set 是一组特定元素的无序集合
var names = {}; // 创建一个空的 Set
elements.add('fluorine'); // 向已存在的 Set 中添加项目
elements.addAll(halogens);
assert(elements.length == 5) // 使用 .length 可以获取 Set 中元素的数量
var halogens = {'fluorine', 'chlorine', 'bromine', 'iodine', 'astatine'}; // 推断 halogens 变量是一个 Set 类型的集合
// 在 Set 变量前添加 const 关键字创建一个 Set 编译时常量
final constantSet = const {
'fluorine',
'chlorine',
'bromine',
'iodine',
'astatine',
};
// constantSet.add('helium'); // This line will cause an error.
Maps (Map)
Map 是用来关联 keys 和 values 的对象。其中键和值都可以是任何类型的对象。每个 键 只能出现一次但是 值 可以重复出现多次(跟js类似,定义/添加键值对/获取值 等)
如果检索的 Key 不存在于 Map 中则会返回一个 null (js 中返回 undefined)
var gifts = {
// Key: Value
'first': 'partridge',
}
// 可以使用 Map 的构造器创建 Map
var gifts = Map();
gifts['first'] = 'partridge';
在一个 Map 字面量前添加 const 关键字可以创建一个 Map 编译时常量(const 对很多类型都是同理)
Map 也可以像 List 一样支持使用扩展操作符(... 和 ...?)以及集合的 if 和 for 操作
Runes (常用于在 Characters API 中进行字符替换)
对于一些特殊字符,表情符号 等 不常用~(Unicode 字符),可以使用 characters 包中定义的 characters
Symbols (Symbol)
可以使用在标识符前加 # 前缀来获取 Symbol,如 #radix
Symbol 字面量是编译时常量
The value null (Null)
基本功能
main()
一个特殊且 必须的 顶级函数,Dart 应用程序总是会从该函数开始执行。
var
用于定义变量,通过这种方式定义变量不需要指定变量类型。这类变量的类型 (int) 由它的初始值决定
print()
一种便利的将信息输出显示的方式
int
表示一个整型数字。 Dart 中一些其他的内置类型包括 String、List 和 bool
void
一种特殊的类型,表示一个值永远不会被使用,以 void 声明的函数返回类型,并不会返回值
Final 和 Const
定义后不可被更改,一个 final 变量只可以被赋值一次;一个 const 变量是一个编译时常量(const 变量同时也是 final 的)
它们的区别在于,const比final更加严格。final只是要求变量在初始化后值不变,但通过final,我们无法在编译时(运行之前)知道这个变量的值;而const所修饰的是编译时常量,我们在编译时就已经知道了它的值,显然,它的值也是不可改变的。
final bad = []; //List
bad.add(1); //正常执行,向变量引用对象添加成员
assert
assert() 的调用将会在生产环境的代码中被忽略掉。在开发过程中,assert(condition) 将会在 条件判断 为 false 时抛出一个异常
一些概念
Dart 中一切皆为对象。所有变量引用的都是 对象,每个对象都是一个 类 的实例。数字、函数以及 null 都是对象。除去 null 以外(如果你开启了 空安全), 所有的类都继承于 Object 类
空安全:变量在未声明为可空类型时不能为 null。你可以通过在类型后加上问号 (?) 将类型声明为可空(跟ts类似)
如果你 明确知道 一个表达式不会为空,但 Dart 不这么认为时,你可以在表达式后添加 ! 来断言表达式不为空 如:int x = nullableButNotNullInt!
Dart 是强类型语言,但是在声明变量时指定类型是可选的,因为 Dart 可以进行类型推断
如果你想要显式地声明允许任意类型,使用 Object。空类型开启则 Object?
Dart 支持泛型,比如 List
Dart 支持顶级 变量,以及定义属于类或对象的变量(静态和实例变量)。实例变量有时称之为 域 或 属性。
Dart 支持顶级函数(例如 main 方法),同时还支持定义属于类或对象的函数(即 静态 和 实例方法)。你还可以在函数中定义函数(嵌套 或 局部函数)
Dart 中 表达式 和 语句 是有区别的,表达式有值而语句没有(跟js其实是一样的)
一个标识符以下划线 (_) 开头则表示该标识符在库内是私有的
如果一个对象的引用不局限于单一的类型,可以将其指定为 Object(或 dynamic)类型
var name = 'Bob'; // 创建一个变量并将其初始化
Object name = 'Bob'; // 任意类型的 name
String name = 'Bob'; // 指定类型为 String
未初始化以及可空类型的变量拥有一个默认的初始值 null
函数
函数也是对象并且类型为 Function
支持默认参数值定义,没有指定默认值的情况下默认值为 null
可以将函数赋值给一个变量或者作为其它函数的参数
所有的函数都有返回值。没有显示返回语句的函数最后一行默认为执行 return null
定义一个函数
bool isNoble(int atomicNumber) {
return _nobleGases[atomicNumber] != null;
}
// 或
isNoble(atomicNumber) {
return _nobleGases[atomicNumber] != null;
}
如果函数体内只包含一个表达式,你可以使用简写语法(箭头函数)
bool isNoble(int atomicNumber) => _nobleGases[atomicNumber] != null;
语法 => 表达式 是 { return 表达式; } 的简写, => 有时也称之为 箭头 函数
参数
有两种形式的参数:必要参数 和 可选参数。必要参数定义在参数列表前面,可选参数则定义在必要参数后面
命名参数
命名参数默认为可选参数,除非他们被特别标记为 required
定义函数时,使用 {参数1, 参数2, …} 来指定命名参数
void enableFlags({bool? bold, bool? hidden}) {...}
当调用函数时,你可以使用 参数名: 参数值 指定一个命名参数的值
enableFlags(bold: true, hidden: false);
使用 required 来标识一个命名参数是必须的参数,此时调用者必须为该参数提供一个值
String printUserInfo(String username, {int age=10, String sex="男"}) {//行参
return "姓名:$username---性别:$sex--年龄:$age";
}
String printInfo(String username, {required int age, required String sex}) {//行参
return "姓名:$username---性别:$sex--年龄:$age";
}
匿名函数
大括号中的内容则为函数体
([[类型] 参数[, …]]) {
函数体;
};
const list = ['apples', 'bananas', 'oranges'];
list.forEach((item) {
print('${list.indexOf(item)}: $item');
});
词法作用域
变量的作用域在写代码的时候就确定了,大括号内定义的变量只能在大括号内访问
词法闭包
闭包 即一个函数对象,即使函数对象的调用在它原始作用域之外,依然能够访问在它词法作用域内的变量
/// Returns a function that adds [addBy] to the
/// function's argument.
Function makeAdder(int addBy) {
return (int i) => addBy + i;
}
void main() {
// Create a function that adds 2.
var add2 = makeAdder(2);
// Create a function that adds 4.
var add4 = makeAdder(4);
assert(add2(3) == 5);
assert(add4(3) == 7);
}
运算符
绝大多数跟 js 差不多,个例需要注意下
算术运算符
跟 js 类似, but 多了一个 ~/ 除并取整(5 ~/ 2 == 2)
关系运算符
跟 js 类似,but 要判断两个对象 x 和 y 是否表示相同的事物使用 == 即可
类型判断运算符
as、is、is! 运算符是在运行时判断对象类型的运算符
as
类型转换(也用作指定 类前缀))
is
如果对象是指定类型则返回 true
is!
如果对象是指定类型则返回 false
赋值运算符
可以使用 = 来赋值,同时也可以
= *= %= >>>= ^=
+= /= <<= &= |=
-= ~/= >>=
// 使用 ??= 来为值为 null 的变量赋值
b ??= value;
// 使用赋值以及复合赋值运算符
var a = 2; // Assign using =
a *= 3; // Assign and multiply: a = a * 3
assert(a == 6);
逻辑运算符
!表达式 对表达式结果取反(即将 true 变为 false,false 变为 true)
|| 逻辑或
&& 逻辑与
& 按位与
| 按位或
^ 按位异或
~表达式 按位取反(即将 “0” 变为 “1”,“1” 变为 “0”)
<< 位左移
位右移
无符号右移
条件表达式
两个特殊的运算符
条件 ? 表达式 1 : 表达式 2
表达式 1 ?? 表达式 2
如果表达式 1 为非 null 则返回其值,否则执行表达式 2 并返回其值
级联运算符
级联运算符 (.., ?..) 可以让你在同一个对象上连续调用多个对象的变量或方法 --不是很理解
流程控制语句
与 js 类似 不作赘述
类
详见:https://dart.cn/guides/langua...
泛型
https://dart.cn/guides/langua...