Dart 學習筆記

Grace糖衣發表於2022-11-24

語法篇

九種內建型別

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 = <String>{}; // 建立一個空的 Set
elements.add('fluorine'); // 向已存在的 Set 中新增專案
elements.addAll(halogens);
assert(elements.length == 5) // 使用 .length 可以獲取 Set 中元素的數量

var halogens = {'fluorine', 'chlorine', 'bromine', 'iodine', 'astatine'}; // 推斷 halogens 變數是一個 Set<String> 型別的集合

// 在 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<String, String>();
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<int>
bad.add(1);    //正常執行,向變數引用物件新增成員

assert
assert() 的呼叫將會在生產環境的程式碼中被忽略掉。在開發過程中,assert(condition) 將會在 條件判斷 為 false 時丟擲一個異常

一些概念
Dart 中一切皆為物件。所有變數引用的都是 物件,每個物件都是一個 類 的例項。數字、函式以及 null 都是物件。除去 null 以外(如果你開啟了 空安全), 所有的類都繼承於 Object 類

空安全:變數在未宣告為可空型別時不能為 null。你可以透過在型別後加上問號 (?) 將型別宣告為可空(跟ts類似)
如果你 明確知道 一個表示式不會為空,但 Dart 不這麼認為時,你可以在表示式後新增 ! 來斷言表示式不為空 如:int x = nullableButNotNullInt!

Dart 是強型別語言,但是在宣告變數時指定型別是可選的,因為 Dart 可以進行型別推斷

如果你想要顯式地宣告允許任意型別,使用 Object。空型別開啟則 Object?

Dart 支援泛型,比如 List<int>(表示一組由 int 物件組成的列表)或 List<Object>(表示一組由任何型別物件組成的列表)

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...

非同步

https://dart.cn/guides/langua...

相關文章