Dart 開發(fā)語(yǔ)言概覽(學(xué)習(xí))

一個(gè)簡(jiǎn)單的 Dart 程序

// 定義一個(gè)函數(shù)雕憔。
printInteger(int aNumber) {
  print('The number is $aNumber.'); // 打印輸出到控制臺(tái)姿骏。
}

// Dart 程序從 main() 函數(shù)開始執(zhí)行。
main() {
  var number = 42; // 聲明并初始化一個(gè)變量斤彼。
  printInteger(number); // 調(diào)用一個(gè)函數(shù)分瘦。
}

// This is a comment.

// 注釋。
以雙斜杠開頭的一行語(yǔ)句稱為單行注釋琉苇。Dart 同樣支持多行注釋和文檔注釋嘲玫。

int

表示一種數(shù)據(jù)類型。Dart 中一些其他的內(nèi)置類型包括 String并扇、Listbool去团。

42

表示一個(gè)數(shù)字字面量。數(shù)字字面量是一種編譯時(shí)常量穷蛹。

print()

一種便利的將信息輸出顯示的方式土陪。

'...' (或 "...")

表示字符串字面量。

variableName (或{expression})

表示字符串插值:字符串字面量中包含的變量或表達(dá)式肴熏。

main()

一個(gè)特殊且 必須的 頂級(jí)函數(shù)鬼雀,Dart 應(yīng)用程序總是會(huì)從該函數(shù)開始執(zhí)行。

var

用于定義變量蛙吏,通過這種方式定義變量不需要指定變量類型源哩。

重要概念

在學(xué)習(xí) Dart 語(yǔ)言時(shí), 應(yīng)該牢記以下幾點(diǎn):

  • 所有變量引用的都是 對(duì)象,每個(gè)對(duì)象都是一個(gè) 的實(shí)例出刷。數(shù)字璧疗、函數(shù)以及 null 都是對(duì)象。所有的類都繼承于 Object 類馁龟。
  • 盡管 Dart 是強(qiáng)類型語(yǔ)言崩侠,但是在聲明變量時(shí)指定類型是可選的,因?yàn)?Dart 可以進(jìn)行類型推斷坷檩。在上述代碼中却音,變量 number 的類型被推斷為 int 類型。如果想顯式地聲明一個(gè)不確定的類型矢炼,可以使用特殊類型 dynamic系瓢。

  • Dart 支持泛型,比如 List<int>(表示一組由 int 對(duì)象組成的列表)或 List<dynamic>(表示一組由任何類型對(duì)象組成的列表)句灌。

  • Dart 支持頂級(jí)函數(shù)(例如 main 方法)夷陋,同時(shí)還支持定義屬于類或?qū)ο蟮暮瘮?shù)(即 靜態(tài)實(shí)例方法)欠拾。你還可以在函數(shù)中定義函數(shù)(嵌套局部函數(shù))。

  • Dart 支持頂級(jí) 變量骗绕,以及定義屬于類或?qū)ο蟮淖兞浚o態(tài)和實(shí)例變量)藐窄。實(shí)例變量有時(shí)稱之為域或?qū)傩浴?/p>

  • Dart 沒有類似于 Java 那樣的 publicprotectedprivate 成員訪問限定符酬土。如果一個(gè)標(biāo)識(shí)符以下劃線 (_) 開頭則表示該標(biāo)識(shí)符在庫(kù)內(nèi)是私有的荆忍。可以查閱 庫(kù)和可見性 獲取更多相關(guān)信息撤缴。

  • 標(biāo)識(shí)符 可以以字母或者下劃線 (_) 開頭刹枉,其后可跟字符和數(shù)字的組合。

  • Dart 中 表達(dá)式語(yǔ)句 是有區(qū)別的屈呕,表達(dá)式有值而語(yǔ)句沒有微宝。比如條件表達(dá)式 expression condition ? expr1 : expr2 中含有值 expr1expr2。與 if-else 分支語(yǔ)句相比虎眨,if-else 分支語(yǔ)句則沒有值芥吟。一個(gè)語(yǔ)句通常包含一個(gè)或多個(gè)表達(dá)式,但是一個(gè)表達(dá)式不能只包含一個(gè)語(yǔ)句专甩。

  • Dart 工具可以顯示 警告錯(cuò)誤 兩種類型的問題。警告表明代碼可能有問題但不會(huì)阻止其運(yùn)行钉稍。錯(cuò)誤分為編譯時(shí)錯(cuò)誤和運(yùn)行時(shí)錯(cuò)誤涤躲;編譯時(shí)錯(cuò)誤代碼無法運(yùn)行;運(yùn)行時(shí)錯(cuò)誤會(huì)在代碼運(yùn)行時(shí)導(dǎo)致異常贡未。

變量

下面的示例代碼將創(chuàng)建一個(gè)變量并將其初始化:

var name = 'Bob';

變量?jī)H存儲(chǔ)對(duì)象的引用种樱。這里名為 name 的變量存儲(chǔ)了一個(gè) String 類型對(duì)象的引用,“Bob” 則是該對(duì)象的值俊卤。

name 變量的類型被推斷為 String嫩挤,但是你可以為其指定類型。如果一個(gè)對(duì)象的引用不局限于單一的類型消恍,可以根據(jù)設(shè)計(jì)指南將其指定為 Objectdynamic 類型岂昭。

dynamic name = 'Bob';

除此之外你也可以指定類型:

String name = 'Bob';

默認(rèn)值

在 Dart 中,未初始化的變量擁有一個(gè)默認(rèn)的初始化值: null狠怨。即便數(shù)字也是如此约啊,因?yàn)樵?Dart 中一切皆為對(duì)象,數(shù)字也不例外佣赖。

int lineCount;
assert(lineCount == null);

Final 和 Const

如果你不想更改一個(gè)變量恰矩,可以使用關(guān)鍵字 final 或者 const 修飾變量,這兩個(gè)關(guān)鍵字可以替代 var 關(guān)鍵字或者加在一個(gè)具體的類型前憎蛤。一個(gè) final 變量只可以被賦值一次外傅;一個(gè) const 變量是一個(gè)編譯時(shí)常量(const 變量同時(shí)也是 final 的)。頂層的 final 變量或者類的 final 變量在其第一次使用的時(shí)候被初始化。
下面的示例中我們創(chuàng)建并設(shè)置兩個(gè) final 變量:

final name = 'Bob'; // 此時(shí) final 替代 var 用于修飾變量名
final String nickname = 'Bobby';// 將 final 加在具體的類型前

你不能修改一個(gè) final 變量的值:

name = 'Alice'; // 錯(cuò)誤:final 變量只能被設(shè)置一次萎胰。

使用關(guān)鍵字 const 修飾變量表示該變量為 編譯時(shí)常量碾盟。如果使用 const 修飾類中的變量,則必須加上 static 關(guān)鍵字奥洼,即 static const(注意:順序不能顛倒(譯者注))巷疼。在聲明 const 變量時(shí)可以直接為其賦值,也可以使用其它的 const 變量為其賦值:

const bar = 1000000; // 直接賦值
const double atm = 1.01325 * bar; // 利用其它 const 變量賦值

const 關(guān)鍵字不僅僅可以用來定義常量灵奖,還可以用來創(chuàng)建 常量值嚼沿,該常量值可以賦予給任何變量。你也可以將構(gòu)造函數(shù)聲明為 const 的瓷患,這種類型的構(gòu)造函數(shù)創(chuàng)建的對(duì)象是不可改變的骡尽。

var foo = const [];
final bar = const [];
const baz = []; // 相當(dāng)于 `const []`

如果使用初始化表達(dá)式為常量賦值可以省略掉關(guān)鍵字 const,比如上面的常量 baz 的賦值就省略掉了 const擅编。
沒有使用 final 或 const 修飾的變量的值是可以被更改的攀细,即使這些變量之前引用過 const 的值。

foo = [1, 2, 3]; // foo 的值之前為 const []

常量的值不可以被修改:

baz = [42]; // 錯(cuò)誤:常量不可以被賦值爱态。

內(nèi)置類型

Dart 語(yǔ)言支持下列的類型:

numbers
strings
booleans
lists (也被稱為 arrays)

sets
maps
runes (用于在字符串中表示 Unicode 字符)

symbols
可以直接使用字面量來初始化上述類型谭贪。例如 'This is a string' 是一個(gè)字符串字面量,true 是一個(gè)布爾字面量锦担。

由于 Dart 中每個(gè)變量引用都指向一個(gè)對(duì)象(一個(gè) 的實(shí)例)俭识,你通常也可以使用 構(gòu)造器 來初始化變量。一些內(nèi)置的類型有它們自己的構(gòu)造器洞渔。例如你可以使用 Map() 來創(chuàng)建一個(gè) map 對(duì)象套媚。

Numbers

Dart 支持兩種 Number 類型
int
整數(shù)值長(zhǎng)度不超過64位具體取值范圍依賴于不同的平臺(tái)。在 DartVM 上其取值位于 -263 至 263 - 1 之間磁椒。編譯成 JavaScript 的 Dart 使用 JavaScript 數(shù)字堤瘤,其允許的取值范圍在 -253 至 253 - 1 之間。
double
64位的雙精度浮點(diǎn)數(shù)字浆熔,且符合 IEEE 754 標(biāo)準(zhǔn)本辐。
intdouble 都是 num 的子類。num 中定義了一些基本的運(yùn)算符比如 +医增、-师郑、*、/ 等调窍,還定義了 abs()宝冕、ceil()floor() 等方法(位運(yùn)算符,比如 ? 定義在 int 中)邓萨。如果 num 及其子類不滿足你的要求地梨,可以查看 dart:math 庫(kù)中的 API菊卷。
整數(shù)是不帶小數(shù)點(diǎn)的數(shù)字。下面是一些定義整數(shù)字面量的例子:

var x = 1;
var hex = 0xDEADBEEF;

如果一個(gè)數(shù)字包含了小數(shù)點(diǎn)宝剖,那么它就是浮點(diǎn)型的洁闰。下面是一些定義浮點(diǎn)數(shù)字面量的例子:

var y = 1.1;
var exponents = 1.42e5;

從 Dart 2.1 開始,整型字面量將會(huì)在必要的時(shí)候自動(dòng)轉(zhuǎn)換成浮點(diǎn)數(shù)字面量:

double z = 1; // 相當(dāng)于 double z = 1.0.

下面是字符串和數(shù)字之間轉(zhuǎn)換的方式:

// String -> int
var one = int.parse('1');
assert(one == 1);

// String -> double
var onePointOne = double.parse('1.1');
assert(onePointOne == 1.1);

// int -> String
String oneAsString = 1.toString();
assert(oneAsString == '1');

// double -> String
String piAsString = 3.14159.toStringAsFixed(2);
assert(piAsString == '3.14');

整型支持傳統(tǒng)的位移操作万细,比如移位(<<扑眉、>>)、按位與(&)赖钞、按位或( )腰素,例如:

assert((3 << 1) == 6); // 0011 << 1 == 0110
assert((3 >> 1) == 1); // 0011 >> 1 == 0001
assert((3 | 4) == 7); // 0011 | 0100 == 0111

數(shù)字字面量為編譯時(shí)常量。很多算術(shù)表達(dá)式只要其操作數(shù)是常量雪营,則表達(dá)式結(jié)果也是編譯時(shí)常量弓千。

const msPerSecond = 1000;
const secondsUntilRetry = 5;
const msUntilRetry = secondsUntilRetry * msPerSecond;

Strings

Dart 字符串是 UTF-16 編碼的字符序列∠灼穑可以使用單引號(hào)或者雙引號(hào)來創(chuàng)建字符串:

var s1 = '使用單引號(hào)創(chuàng)建字符串字面量洋访。';
var s2 = "雙引號(hào)也可以用于創(chuàng)建字符串字面量。";
var s3 = '使用單引號(hào)創(chuàng)建字符串時(shí)可以使用斜杠來轉(zhuǎn)義那些與單引號(hào)沖突的字符串:\'谴餐。';
var s4 = "而在雙引號(hào)中則不需要使用轉(zhuǎn)義與單引號(hào)沖突的字符串:'";

可以在字符串中以 ${表達(dá)式} 的形式使用表達(dá)式姻政,如果表達(dá)式是一個(gè)標(biāo)識(shí)符,可以省略掉 {}岂嗓。如果表達(dá)式的結(jié)果為一個(gè)對(duì)象扶歪,則 Dart 會(huì)調(diào)用該對(duì)象的 toString 方法來獲取一個(gè)字符串。

var s = '字符串插值';

assert('Dart 有$s摄闸,使用起來非常方便。' == 'Dart 有字符串插值妹萨,使用起來非常方便年枕。');
assert('使用${s.substring(3,5)}表達(dá)式也非常方便' == '使用插值表達(dá)式也非常方便。');

可以使用 + 運(yùn)算符將兩個(gè)字符串連接為一個(gè)乎完,也可以將多個(gè)字符串挨著放一起變?yōu)橐粋€(gè):

var s1 = '可以拼接'
    '字符串'
    "即便它們不在同一行熏兄。";
assert(s1 == '可以拼接字符串即便它們不在同一行。');

var s2 = '使用加號(hào) + 運(yùn)算符' + '也可以達(dá)到相同的效果树姨。';
assert(s2 == '使用加號(hào) + 運(yùn)算符也可以達(dá)到相同的效果摩桶。');

可以使用三個(gè)單引號(hào)或者三個(gè)雙引號(hào)創(chuàng)建多行字符串:

var s1 = '''
你可以像這樣創(chuàng)建多行字符串。
''';

var s2 = """這也是一個(gè)多行字符串帽揪。""";

在字符串前加上 r 作為前綴創(chuàng)建 “raw” 字符串(即不會(huì)被做任何處理(比如轉(zhuǎn)義)的字符串):

var s = r'在 raw 字符串中硝清,轉(zhuǎn)義字符串 \n 會(huì)直接輸出 “\n” 而不是轉(zhuǎn)義為換行。';

字符串字面量是一個(gè)編譯時(shí)常量转晰,只要是編譯時(shí)常量都可以作為字符串字面量的插值表達(dá)式:

// 可以將下面三個(gè)常量作為字符串插值拼接到字符串字面量中芦拿。
const aConstNum = 0;
const aConstBool = true;
const aConstString = 'a constant string';

// 而下面三個(gè)常量則不能作為字符串插值拼接到字符串字面量士飒。
var aNum = 0;
var aBool = true;
var aString = 'a string';
const aConstList = [1, 2, 3];

const validConstString = '$aConstNum $aConstBool $aConstString';
// const invalidConstString = '$aNum $aBool $aString $aConstList';

Booleans

Dart 使用 bool 關(guān)鍵字表示布爾類型,布爾類型只有兩個(gè)對(duì)象 true 和 false蔗崎,兩者都是編譯時(shí)常量酵幕。

Dart 的類型安全不允許你使用類似 if (nonbooleanValue) 或者 assert (nonbooleanValue) 這樣的代碼檢查布爾值。相反缓苛,你應(yīng)該總是顯示地檢查布爾值芳撒,比如像下面的代碼這樣:

// 檢查是否為空字符串。
var fullName = '';
assert(fullName.isEmpty);

// 檢查是否小于等于零未桥。
var hitPoints = 0;
assert(hitPoints <= 0);

// 檢查是否為 null笔刹。
var unicorn;
assert(unicorn == null);

// 檢查是否為 NaN。
var iMeantToDoThis = 0 / 0;
assert(iMeantToDoThis.isNaN);

Lists

數(shù)組 Array 是幾乎所有編程語(yǔ)言中最常見的集合類型钢属,在 Dart 中數(shù)組由 List 對(duì)象表示徘熔。通常稱之為 List

Dart 中 List 字面量看起來與 JavaScript 中數(shù)組字面量一樣淆党。下面是一個(gè) Dart List 的示例:\

var list = [1, 2, 3];

List 的下標(biāo)索引從 0 開始酷师,第一個(gè)元素的下標(biāo)為 0,最后一個(gè)元素的下標(biāo)為 list.length - 1染乌。你可以像 JavaScript 中的用法那樣獲取 Dart 中 List 的長(zhǎng)度以及元素:

var list = [1, 2, 3];
assert(list.length == 3);
assert(list[1] == 2);

list[1] = 1;
assert(list[1] == 1);

如果想要?jiǎng)?chuàng)建一個(gè)編譯時(shí)常量的 List山孔,在 List 字面量前添加 const 關(guān)鍵字即可:

var constantList = const [1, 2, 3];
// constantList[1] = 1; // 取消注釋將導(dǎo)致出錯(cuò)。

Dart 在 2.3 引入了 擴(kuò)展操作符(...)和 null-aware 擴(kuò)展操作符(...?)荷憋,它們提供了一種將多個(gè)元素插入集合的簡(jiǎn)潔方法台颠。

例如,你可以使用擴(kuò)展操作符(...)將一個(gè) List 中的所有元素插入到另一個(gè) List 中:

var list = [1, 2, 3];
var list2 = [0, ...list];
assert(list2.length == 4);

如果擴(kuò)展操作符右邊可能為 null 勒庄,你可以使用 null-aware 擴(kuò)展操作符(...?)來避免產(chǎn)生異常:

var list;
var list2 = [0, ...?list];
assert(list2.length == 1);

Dart 在 2.3 還同時(shí)引入了 Collection If 和 Collection For串前,在構(gòu)建集合時(shí),可以使用條件判斷(if)和循環(huán)(for)实蔽。

下面示例是使用 Collection If 來創(chuàng)建一個(gè) List 的示例荡碾,它可能包含 3 個(gè)或 4 個(gè)元素:

var nav = [
  'Home',
  'Furniture',
  'Plants',
  if (promoActive) 'Outlet'
];

下面示例是使用 Collection For 將列表中的元素修改后添加到另一個(gè)列表中的示例:

var listOfInts = [1, 2, 3];
var listOfStrings = [
  '#0',
  for (var i in listOfInts) '#$i'
];
assert(listOfStrings[1] == '#1');

List 類中有許多用于操作 List 的便捷方法,你可以查閱泛型集合獲取更多與之相關(guān)的信息局装。

Sets

Dart 中使用 Set 來表示無序且元素唯一的集合坛吁,Dart 支持 Set 字面量以及 Set 類型兩種形式的 Set。

下面是使用 Set 字面量來創(chuàng)建一個(gè) Set 集合的方法:

var halogens = {'fluorine', 'chlorine', 'bromine', 'iodine', 'astatine'};

Dart 推斷halogens變量是一個(gè)Set<String>類型的集合铐尚,如果往該 Set 中添加類型不正確的對(duì)象則會(huì)報(bào)錯(cuò)拨脉。你可以查閱類型推斷獲取更多與之相關(guān)的內(nèi)容。
可以使用在 {} 前加上類型參數(shù)的方式創(chuàng)建一個(gè)空的 Set宣增,或者將 {} 賦值給一個(gè) Set 類型的變量:

var names = <String>{};// 類型+{}的形式創(chuàng)建Set玫膀。
// Set<String> names = {}; // 聲明類型變量的形式創(chuàng)建 Set。
// var names = {}; // 這樣的形式將創(chuàng)建一個(gè) Map 而不是 Set爹脾。

Map 字面量語(yǔ)法同 Set 字面量語(yǔ)法非常相似匆骗。因?yàn)橄扔械?Map 字面量語(yǔ)法劳景,所以 {} 默認(rèn)是 Map 類型。如果忘記在 {} 上注釋類型或賦值到一個(gè)未聲明類型的變量上碉就,那么 Dart 會(huì)創(chuàng)建一個(gè)類型為 Map<dynamic, dynamic> 的對(duì)象盟广。
向一個(gè)已存在的 Set 中添加項(xiàng)目可以使用 add() 方法或 addAll() 方法:

var elements = <String>{};
elements.add('fluorine');
elements.addAll(halogens);

使用 .length 可以獲取 Set 中元素的數(shù)量:

var elements = <String>{};
elements.add('fluorine');
elements.addAll(halogens);
assert(elements.length == 5);

可以在 Set 字面量前添加 const 關(guān)鍵字創(chuàng)建一個(gè) Set 編譯時(shí)常量:

final constantSet = const {
  'fluorine',
  'chlorine',
  'bromine',
  'iodine',
  'astatine',
};
// constantSet.add('helium'); // 取消注釋將導(dǎo)致出錯(cuò)。

從 Dart 2.3 開始瓮钥,Set 可以像 List 一樣支持使用擴(kuò)展操作符(......?)以及 Collection If 和 Collection For 操作筋量。你可以查閱 List 擴(kuò)展操作符List 集合操作符獲取更多相關(guān)信息。

Maps

通常來說碉熄, Map 是用來關(guān)聯(lián) keys 和 values 的對(duì)象桨武。 keys 和 values 可以是任何類型的對(duì)象。在一個(gè) Map 對(duì)象中一個(gè) key 只能出現(xiàn)一次锈津。但是 value 可以出現(xiàn)多次呀酸。 Dart 中 Map 通過 Map 字面量和 Map 類型來實(shí)現(xiàn)。通常來說琼梆,Map 是一個(gè)鍵值對(duì)相關(guān)的對(duì)象性誉。其中鍵和值都可以是任何類型的對(duì)象错览。每個(gè) 只能出現(xiàn)一次但是 可以重復(fù)出現(xiàn)多次。Dart 中 Map 提供了 Map 字面量以及 Map 類型兩種形式的 Map。
下面是一對(duì)使用 Map 字面量創(chuàng)建 Map 的例子:

var gifts = {
  // 鍵:    值
  'first': 'partridge',
  'second': 'turtledoves',
  'fifth': 'golden rings'
};

var nobleGases = {
  2: 'helium',
  10: 'neon',
  18: 'argon',
};
  • Dart 將 gifts 變量的類型推斷為 Map<String, String>,而降 nobleGases 的類型推斷為 Map<int, String>癌幕。如果你向這兩個(gè) Map 對(duì)象中添加不正確的類型值,將導(dǎo)致運(yùn)行時(shí)異常厅瞎。你可以閱讀類型推斷獲取更多相關(guān)信息。
    你也可以使用 Map 的構(gòu)造器創(chuàng)建 Map:
var gifts = Map();
gifts['first'] = 'partridge';
gifts['second'] = 'turtledoves';
gifts['fifth'] = 'golden rings';

var nobleGases = Map();
nobleGases[2] = 'helium';
nobleGases[10] = 'neon';
nobleGases[18] = 'argon';
  • 這里為什么使用 Map() 而不是使用 new Map() 構(gòu)造 Map 對(duì)象。因?yàn)閺?Dart2 開始,構(gòu)造對(duì)象的 new 關(guān)鍵字可以被省略掉畔勤。你可以查閱構(gòu)造函數(shù)的使用獲取更多相關(guān)信息。

向現(xiàn)有的 Map 中添加鍵值對(duì)與 JavaScript 的操作類似:
var gifts = {'first': 'partridge'};
gifts['fourth'] = 'calling birds'; // 添加鍵值對(duì)

從一個(gè) Map 中獲取一個(gè)值的操作也與 JavaScript 類似。

var gifts = {'first': 'partridge'};
assert(gifts['first'] == 'partridge');

如果檢索的 Key 不存在于 Map 中則會(huì)返回一個(gè) null:

var gifts = {'first': 'partridge'};
assert(gifts['fifth'] == null);

使用 .length 可以獲取 Map 中鍵值對(duì)的數(shù)量:

var gifts = {'first': 'partridge'};
gifts['fourth'] = 'calling birds';
assert(gifts.length == 2);

在一個(gè) Map 字面量前添加 const 關(guān)鍵字可以創(chuàng)建一個(gè) Map 編譯時(shí)常量:

final constantMap = const {
  2: 'helium',
  10: 'neon',
  18: 'argon',
};

// constantMap[2] = 'Helium'; // 取消注釋將導(dǎo)致出錯(cuò)。

從 Dart 2.3 Map 可以像 List 一樣支持使用擴(kuò)展操作符(......?)以及 Collection If 和 Collection For 操作。你可以查閱 List 擴(kuò)展操作符List 集合操作符獲取更多相關(guān)信息。

Runes

Dart 使用 Runes 符文來表示 UTF-32 編碼的字符串。

Unicode 編碼為每一個(gè)字母竣付、數(shù)字和符號(hào)都定義了一個(gè)唯一的數(shù)值筛璧。因?yàn)?Dart 中的字符串是一個(gè) UTF-16 的字符序列巫糙,所以如果想要表示 32 位的 Unicode 數(shù)值則需要一種特殊的語(yǔ)法疲牵。

通常使用 \uXXXX 來表示 Unicode 字符,XXXX 是一個(gè)四位數(shù)的 16 進(jìn)制數(shù)字。例如心形字符(?)的 Unicode 為 \u2665。對(duì)于不是四位數(shù)的 16 進(jìn)制數(shù)字,需要使用大括號(hào)將其括起來。例如大笑的 emoji 表情(??)的 Unicode 為 \u{1f600}徒溪。

String 類中有一些屬性可以用來提取字符串的 Rune 符文信息。codeUnitAtcodeUnit 屬性返回 16 位代碼單元高氮。runes 屬性可以獲取字符串的 Runes 符文。

Symbols

Symbol 表示 Dart 中聲明的操作符或者標(biāo)識(shí)符,該類型的對(duì)象幾乎不會(huì)被使用到峡继,但是如果需要按名稱引用它們的 API 時(shí)就非常有用。因?yàn)榇a壓縮后會(huì)改變這些符號(hào)的名稱但不會(huì)改變具體的符號(hào)。

可以使用在標(biāo)識(shí)符前加 # 前綴來獲取 Symbol:

#radix
#bar

Symbol 字面量是編譯時(shí)常量踊赠。

Functions

Dart 是一種真正面向?qū)ο蟮恼Z(yǔ)言伦籍,所以即便函數(shù)也是對(duì)象并且類型為 Function作儿,這意味著函數(shù)可以被賦值給變量或者作為其它函數(shù)的參數(shù)。你也可以像調(diào)用函數(shù)一樣調(diào)用 Dart 類的實(shí)例机断。詳情請(qǐng)查閱 可調(diào)用的類奋蔚。
下面是定義一個(gè)函數(shù)的例子:

bool isNoble(int atomicNumber) {
  return _nobleGases[atomicNumber] != null;
}

雖然高效 Dart 指南建議在公開的 API 上定義返回類型晋涣,不過即便不定義佃扼,該函數(shù)也依然有效:

isNoble(atomicNumber) {
  return _nobleGases[atomicNumber] != null;
}

如果函數(shù)體內(nèi)只包含一個(gè)表達(dá)式匠题,你可以使用簡(jiǎn)寫語(yǔ)法:

bool isNoble(int atomicNumber) => _nobleGases[atomicNumber] != null;

語(yǔ)法 => 表達(dá)式 是 { return 表達(dá)式; } 的簡(jiǎn)寫梦裂,=> 有時(shí)也稱之為胖箭頭語(yǔ)法牵咙。

  • 在 => 與 ; 之間的只能是 表達(dá)式 而非 語(yǔ)句谱轨。比如你不能將一個(gè) if語(yǔ)句 放在其中王污,但是可以放置 條件表達(dá)式啊易。

函數(shù)可以有兩種形式的參數(shù):必要參數(shù) 和 可選參數(shù)窟却。必要參數(shù)定義在參數(shù)列表前面昼丑,可選參數(shù)則定義在必要參數(shù)后面】浜眨可選參數(shù)可以是 命名的 或 位置的菩帝。

可選參數(shù)

可選參數(shù)分為命名參數(shù)和位置參數(shù),可在參數(shù)列表中任選其一使用茬腿,但兩者不能同時(shí)出現(xiàn)在參數(shù)列表中呼奢。

命名參數(shù)

當(dāng)你調(diào)用函數(shù)時(shí),可以使用 參數(shù)名: 參數(shù)值 的形式來指定命名參數(shù)切平。例如:

enableFlags(bold: true, hidden: false);

定義函數(shù)時(shí)握础,使用 {param1, param2, …} 來指定命名參數(shù):

/// 設(shè)置 [bold] 和 [hidden] 標(biāo)識(shí)……
void enableFlags({bool bold, bool hidden}) {...}

雖然命名參數(shù)是可選參數(shù)的一種類型,但是你仍然可以使用 @required 注解來標(biāo)識(shí)一個(gè)命名參數(shù)是必須的參數(shù)悴品,此時(shí)調(diào)用者則必須為該參數(shù)提供一個(gè)值禀综。例如:

const Scrollbar({Key key, @required Widget child})

如果調(diào)用者想要通過 Scrollbar 的構(gòu)造函數(shù)構(gòu)造一個(gè) Scrollbar 對(duì)象而不提供 child 參數(shù),則會(huì)導(dǎo)致編譯錯(cuò)誤苔严。

@required 注解定義在 meta 包中定枷,可以直接導(dǎo)入 package:meta/meta.dart 包使用。

位置參數(shù)

使用 [] 將一系列參數(shù)包裹起來作為位置參數(shù):

String say(String from, String msg, [String device]) {
  var result = '$from says $msg';
  if (device != null) {
    result = '$result with a $device';
  }
  return result;
}

下面是不使用可選參數(shù)調(diào)用上述函數(shù)的示例:

assert(say('Bob', 'Howdy') == 'Bob says Howdy');

下面是使用可選參數(shù)調(diào)用上述函數(shù)的示例:

assert(say('Bob', 'Howdy', 'smoke signal') ==
    'Bob says Howdy with a smoke signal');

默認(rèn)參數(shù)值
可以用 = 為函數(shù)的命名和位置參數(shù)定義默認(rèn)值届氢,默認(rèn)值必須為編譯時(shí)常量依鸥,沒有指定默認(rèn)值的情況下默認(rèn)值為 null。

下面是設(shè)置可選參數(shù)默認(rèn)值示例:

/// 設(shè)置 [bold] 和 [hidden] 標(biāo)識(shí)……
void enableFlags({bool bold = false, bool hidden = false}) {...}

// bold 的值將為 true悼沈;而 hidden 將為 false贱迟。
enableFlags(bold: true);
  • 在老版本的 Dart 代碼中會(huì)使用冒號(hào)(:)而不是 = 來設(shè)置命名參數(shù)的默認(rèn)值。原因在于剛開始的時(shí)候命名參數(shù)只支持 :絮供。不過現(xiàn)在這個(gè)支持已經(jīng)過時(shí)衣吠,所以我們建議你現(xiàn)在都 使用 = 來指定默認(rèn)值。
String say(String from, String msg,
    [String device = 'carrier pigeon', String mood]) {
  var result = '$from says $msg';
  if (device != null) {
    result = '$result with a $device';
  }
  if (mood != null) {
    result = '$result (in a $mood mood)';
  }
  return result;
}

assert(say('Bob', 'Howdy') ==
    'Bob says Howdy with a carrier pigeon');

List 或 Map 同樣也可以作為默認(rèn)值壤靶。下面的示例定義了一個(gè)名為 doStuff() 的函數(shù)缚俏,并為其名為 list 和 gifts 的參數(shù)指定了一個(gè) List 類型的值和 Map 類型的值。

void doStuff(
    {List<int> list = const [1, 2, 3],
    Map<String, String> gifts = const {
      'first': 'paper',
      'second': 'cotton',
      'third': 'leather'
    }}) {
  print('list:  $list');
  print('gifts: $gifts');
}

main() 函數(shù)

每個(gè) Dart 程序都必須有一個(gè) main() 頂級(jí)函數(shù)作為程序的入口贮乳,main() 函數(shù)返回值為 void 并且有一個(gè) List<String> 類型的可選參數(shù)忧换。

下面是一個(gè) Web 應(yīng)用的 main() 函數(shù)示例:

void main() {
  querySelector('#sample_text_id')
    ..text = 'Click me!'
    ..onClick.listen(reverseText);
}
  • 上述代碼中的 .. 語(yǔ)法稱之為 級(jí)聯(lián)調(diào)用。使用級(jí)聯(lián)訪問可以在一個(gè)對(duì)象上執(zhí)行多個(gè)操作向拆。

下面是使用命令行訪問帶參數(shù)的 main() 函數(shù)示例:

// 使用命令 dart args.dart 1 test 運(yùn)行該應(yīng)用
void main(List<String> arguments) {
  print(arguments);

  assert(arguments.length == 2);
  assert(int.parse(arguments[0]) == 1);
  assert(arguments[1] == 'test');
}

你可以通過使用 參數(shù)庫(kù) 來定義和解析命令行參數(shù)亚茬。

函數(shù)作為一級(jí)對(duì)象

可以將函數(shù)作為參數(shù)傳遞給另一個(gè)函數(shù)。例如:

void printElement(int element) {
  print(element);
}

var list = [1, 2, 3];

// 將 printElement 函數(shù)作為參數(shù)傳遞浓恳。
list.forEach(printElement);

你也可以將函數(shù)賦值給一個(gè)變量刹缝,比如:

var loudify = (msg) => '!!! ${msg.toUpperCase()} !!!';
assert(loudify('hello') == '!!! HELLO !!!');

該示例中使用了匿名函數(shù)碗暗。下一節(jié)會(huì)有更多與其相關(guān)的介紹。

匿名函數(shù)

大多數(shù)方法都是有名字的梢夯,比如 main()printElement()言疗。你可以創(chuàng)建一個(gè)沒有名字的方法,稱之為 匿名函數(shù)颂砸,或 Lambda表達(dá)式Closure閉包噪奄。你可以將匿名方法賦值給一個(gè)變量然后使用它,比如將該變量添加到集合或從中刪除人乓。

匿名方法看起來與命名方法類似勤篮,在括號(hào)之間可以定義參數(shù),參數(shù)之間用逗號(hào)分割撒蟀。

后面大括號(hào)中的內(nèi)容則為函數(shù)體:

([[*類型*] *參數(shù)*[, …]]) { *函數(shù)體*; };

下面代碼定義了只有一個(gè)參數(shù) item 且沒有參數(shù)類型的匿名方法。List 中的每個(gè)元素都會(huì)調(diào)用這個(gè)函數(shù)温鸽,打印元素位置和值的字符串:

var list = ['apples', 'bananas', 'oranges'];
list.forEach((item) {
  print('${list.indexOf(item)}: $item');
});

詞法作用域

Dart 是詞法有作用域語(yǔ)言保屯,變量的作用域在寫代碼的時(shí)候就確定了,大括號(hào)內(nèi)定義的變量只能在大括號(hào)內(nèi)訪問涤垫,與 Java 類似姑尺。

下面是一個(gè)嵌套函數(shù)中變量在多個(gè)作用域中的示例:

bool topLevel = true;

void main() {
  var insideMain = true;

  void myFunction() {
    var insideFunction = true;

    void nestedFunction() {
      var insideNestedFunction = true;

      assert(topLevel);
      assert(insideMain);
      assert(insideFunction);
      assert(insideNestedFunction);
    }
  }
}

注意 nestedFunction() 函數(shù)可以訪問包括頂層變量在內(nèi)的所有的變量。

詞法閉包

閉包 即一個(gè)函數(shù)對(duì)象蝠猬,即使函數(shù)對(duì)象的調(diào)用在它原始作用域之外切蟋,依然能夠訪問在它詞法作用域內(nèi)的變量。

函數(shù)可以封閉定義到它作用域內(nèi)的變量榆芦。接下來的示例中柄粹,函數(shù) makeAdder() 捕獲了變量 addBy。無論函數(shù)在什么時(shí)候返回匆绣,它都可以使用捕獲的 addBy 變量驻右。

/// 返回一個(gè)將 [addBy] 添加到該函數(shù)參數(shù)的函數(shù)。
Function makeAdder(num addBy) {
  return (num i) => addBy + i;
}

void main() {
  // 生成加 2 的函數(shù)崎淳。
  var add2 = makeAdder(2);

  // 生成加 4 的函數(shù)堪夭。
  var add4 = makeAdder(4);

  assert(add2(3) == 5);
  assert(add4(3) == 7);
}

測(cè)試函數(shù)是否相等

下面是頂級(jí)函數(shù),靜態(tài)方法和示例方法相等性的測(cè)試示例:

void foo() {} // 定義頂層函數(shù)

class A {
  static void bar() {} // 定義靜態(tài)方法
  void baz() {} // 定義實(shí)例方法
}

void main() {
  var x;

  // 比較頂層函數(shù)是否相等拣凹。
  x = foo;
  assert(foo == x);

  // 比較靜態(tài)方法是否相等森爽。
  x = A.bar;
  assert(A.bar == x);

  // 比較實(shí)例方法是否相等。
  var v = A(); // A 的實(shí)例 #1
  var w = A(); // A 的實(shí)例 #2
  var y = w;
  x = w.baz;

  // 這兩個(gè)閉包引用了相同的實(shí)例對(duì)象嚣镜,因此它們相等爬迟。
  assert(y.baz == x);

  // 這兩個(gè)閉包引用了不同的實(shí)例對(duì)象,因此它們不相等菊匿。
  assert(v.baz != w.baz);
}

返回值

所有的函數(shù)都有返回值雕旨。沒有顯示返回語(yǔ)句的函數(shù)最后一行默認(rèn)為執(zhí)行 return null;扮匠。

foo() {}

assert(foo() == null);

運(yùn)算符

下表是 Dart 中定義的運(yùn)算符,很多運(yùn)算符都可以重寫凡涩。詳情參考重寫運(yùn)算符棒搜。
描述 運(yùn)算符
一元后綴 表達(dá)式++ 表達(dá)式-- () [] . ?.
一元前綴 -表達(dá)式 !表達(dá)式 ~表達(dá)式 ++表達(dá)式 --表達(dá)式
乘除法 * / % ~/
加減法 + -
位運(yùn)算 << >> >>>
二進(jìn)制與 &
二進(jìn)制異或 ^
二進(jìn)制或 |
關(guān)系和類型測(cè)試 >= > <= < as is is!
相等判斷 == !=
邏輯與 &&
邏輯或 ||
空判斷 ??
條件表達(dá)式 表達(dá)式 1 ? 表達(dá)式 2 : 表達(dá)式 3
級(jí)聯(lián) ..
賦值 = *= /= += -= &= ^= 等等……

一旦你使用了運(yùn)算符,就創(chuàng)建了表達(dá)式活箕。下面是一些運(yùn)算符表達(dá)式的示例:

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

運(yùn)算符表 中力麸,運(yùn)算符的優(yōu)先級(jí)按先后排列,即第一行優(yōu)先級(jí)最高育韩,最后一行優(yōu)先級(jí)最低克蚂,而同一行中,最左邊的優(yōu)先級(jí)最高筋讨,最右邊的優(yōu)先級(jí)最低埃叭。例如:% 運(yùn)算符優(yōu)先級(jí)高于 == ,而 == 高于 &&悉罕。根據(jù)優(yōu)先級(jí)規(guī)則赤屋,那么意味著以下兩行代碼執(zhí)行的效果相同:

// 括號(hào)提高了可讀性。
if ((n % i == 0) && (d % i == 0)) ...

// 難以理解壁袄,但是與上面的代碼效果一樣类早。
if (n % i == 0 && d % i == 0) ...
  • 對(duì)于有兩個(gè)操作數(shù)的運(yùn)算符,左邊的操作數(shù)決定了運(yùn)算符的功能嗜逻。比如如果有一個(gè) Vector 對(duì)象和一個(gè) Point 對(duì)象涩僻,表達(dá)式 aVector + aPoint 中所使用的是 Vector 對(duì)象中定義的 + 運(yùn)算符。

算術(shù)運(yùn)算符

Dart 支持常用的算術(shù)運(yùn)算符:

運(yùn)算符 描述


  • – 減
    -表達(dá)式 一元負(fù), 也可以作為反轉(zhuǎn)(反轉(zhuǎn)表達(dá)式的符號(hào))

  • / 除
    ~/ 除并取整
    % 取模
assert(2 + 3 == 5);
assert(2 - 3 == -1);
assert(2 * 3 == 6);
assert(5 / 2 == 2.5); // 結(jié)果是一個(gè)浮點(diǎn)數(shù)
assert(5 ~/ 2 == 2); // 結(jié)果是一個(gè)整數(shù)
assert(5 % 2 == 1); // 取余

assert('5/2 = ${5 ~/ 2} r ${5 % 2}' == '5/2 = 2 r 1');

Dart 還支持自增自減操作栈顷。

Operator

++var

var = var + 1 (表達(dá)式的值為 var + 1)

var++ var = var + 1 (表達(dá)式的值為 var)
--var var = var – 1 (表達(dá)式的值為 var – 1)
var-- var = var – 1 (表達(dá)式的值為 var)

var a, b;

a = 0;
b = ++a; // 在 b 賦值前將 a 增加 1逆日。
assert(a == b); // 1 == 1

a = 0;
b = a++; // 在 b 賦值后將 a 增加 1。
assert(a != b); // 1 != 0

a = 0;
b = --a; // 在 b 賦值前將 a 減少 1萄凤。
assert(a == b); // -1 == -1

a = 0;
b = a--; // 在 b 賦值后將 a 減少 1屏富。
assert(a != b); // -1 != 0

關(guān)系運(yùn)算符

下表列出了關(guān)系運(yùn)算符及含義:

|

Operator

==

|

相等

|
| --- | --- |
| != | 不等 |
| > | 大于 |
| < | 小于 |
| >= | 大于等于 |
| <= | 小于等于 |

要判斷兩個(gè)對(duì)象 x 和 y 是否表示相同的事物使用 == 即可。(在極少數(shù)情況下蛙卤,可能需要使用 identical() 函數(shù)來確定兩個(gè)對(duì)象是否完全相同狠半。)。下面是 == 運(yùn)算符的一些規(guī)則:

  1. 假設(shè)有變量 xy颤难,且 x 和 y 至少有一個(gè)為 null神年,則當(dāng)且僅當(dāng) x 和 y 均為 null 時(shí) x == y 才會(huì)返回 true,否則只有一個(gè)為 null 則返回 false行嗤。

  2. *x*.==(*y*) 將會(huì)返回值已日,這里不管有沒有 y,即 y 是可選的栅屏。也就是說 == 其實(shí)是 x 中的一個(gè)方法飘千,并且可以被重寫堂鲜。詳情請(qǐng)查閱重寫運(yùn)算符

下面的代碼給出了每一種關(guān)系運(yùn)算符的示例:

assert(2 == 2);
assert(2 != 3);
assert(3 > 2);
assert(2 < 3);
assert(3 >= 3);
assert(2 <= 3);

類型判斷運(yùn)算符

as护奈、is缔莲、is! 運(yùn)算符是在運(yùn)行時(shí)判斷對(duì)象類型的運(yùn)算符。

|

Operator

as

|

類型轉(zhuǎn)換(也用作指定類前綴))

|
| --- | --- |
| is | 如果對(duì)象是指定類型則返回 true |
| is! | 如果對(duì)象是指定類型則返回 false |

當(dāng)且僅當(dāng) obj 實(shí)現(xiàn)了 T 的接口霉旗,obj is T 才是 true痴奏。例如 obj is Object 總為 true,因?yàn)樗蓄惗际?Object 的子類厌秒。

使用 as 操作符可以把對(duì)象轉(zhuǎn)換為特定的類型读拆。一般情況下可以將其當(dāng)做 is 判定類型后調(diào)用所判定對(duì)象的函數(shù)的縮寫形式。假設(shè)有如下代碼:

if (emp is Person) {
  // 類型檢查
  emp.firstName = 'Bob';
}

你可以使用 as 運(yùn)算符進(jìn)行縮寫:

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

賦值運(yùn)算符

可以使用 = 來賦值鸵闪,同時(shí)也可以使用 ??= 來為值為 null 的變量賦值檐晕。

// 將 value 賦值給 a
a = value;
// 當(dāng)且僅當(dāng) b 為 null 時(shí)才賦值
b ??= value;

像 += 這樣的賦值運(yùn)算符將算數(shù)運(yùn)算符和賦值運(yùn)算符組合在了一起。

var a = 2; // 使用 = 賦值
a *= 3; // 賦值并做乘法運(yùn)算:a = a * 3
assert(a == 6);

邏輯運(yùn)算符

使用邏輯運(yùn)算符你可以反轉(zhuǎn)或組合布爾表達(dá)式蚌讼。

運(yùn)算符 描述
!!表達(dá)式 對(duì)表達(dá)式結(jié)果取反(即將 true 變?yōu)?false辟灰,false 變?yōu)?true)
|| 邏輯或
&& 邏輯與

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

按位和移位運(yùn)算符

在 Dart 中,二進(jìn)制位運(yùn)算符可以操作二進(jìn)制的某一位啦逆,但僅適用于整數(shù)伞矩。
& 按位與
| 按位或
^ 按位異或
~表達(dá)式 按位取反(即將 “0” 變?yōu)?“1”笛洛,“1” 變?yōu)?“0”)
<< 位左移

位右移

final value = 0x22;
final bitmask = 0x0f;

assert((value & bitmask) == 0x02); // 按位與
assert((value & ~bitmask) == 0x20); // 取反后按位與
assert((value | bitmask) == 0x2f); // 按位或
assert((value ^ bitmask) == 0x2d); // 按位異或
assert((value << 4) == 0x220); // 位左移
assert((value >> 4) == 0x02); // 位右移

條件表達(dá)式

Dart 有兩個(gè)特殊的運(yùn)算符可以用來替代 if-else 語(yǔ)句:
condition ? expr1 : expr2
條件 ? 表達(dá)式 1 : 表達(dá)式 2:如果條件為 true夏志,執(zhí)行表達(dá)式 1并返回執(zhí)行結(jié)果,否則執(zhí)行表達(dá)式 2 并返回執(zhí)行結(jié)果苛让。
expr1 ?? expr2
表達(dá)式 1 ?? 表達(dá)式 2:如果表達(dá)式 1 為非 null 則返回其值沟蔑,否則執(zhí)行表達(dá)式 2 并返回其值。

如果賦值是根據(jù)布爾表達(dá)式則考慮使用 ?:狱杰。

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

如果賦值是根據(jù)判定是否為 null 則考慮使用??瘦材。

String playerName(String name) => name ?? 'Guest';
// 相對(duì)使用 ?: 運(yùn)算符來說稍微長(zhǎng)了點(diǎn)。
String playerName(String name) => name != null ? name : 'Guest';

// 如果使用 if-else 則更長(zhǎng)仿畸。
String playerName(String name) {
  if (name != null) {
    return name;
  } else {
    return 'Guest';
  }
}

級(jí)聯(lián)運(yùn)算符(..)

級(jí)聯(lián)運(yùn)算符(..)可以讓你在同一個(gè)對(duì)象上連續(xù)調(diào)用多個(gè)對(duì)象的變量或方法食棕。

比如下面的代碼:

querySelector('#confirm') // 獲取對(duì)象。
  ..text = 'Confirm' // 使用對(duì)象的成員错沽。
  ..classes.add('important')
  ..onClick.listen((e) => window.alert('Confirmed!'));

第一個(gè)方法 querySelector 返回了一個(gè) Selector 對(duì)象簿晓,后面的級(jí)聯(lián)操作符都是調(diào)用這個(gè) Selector 對(duì)象的成員并忽略每個(gè)操作的返回值。

上面的代碼相當(dāng)于:

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

級(jí)聯(lián)運(yùn)算符可以嵌套千埃,例如:

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

在返回對(duì)象的函數(shù)中謹(jǐn)慎使用級(jí)聯(lián)操作符憔儿。例如,下面的代碼是錯(cuò)誤的:

var sb = StringBuffer();
sb.write('foo')
  ..write('bar'); // 出錯(cuò):void 對(duì)象中沒有方法 write放可。

上述代碼中的 sb.write() 方法返回的是 void谒臼,返回值為 void 的方法則不能使用級(jí)聯(lián)運(yùn)算符朝刊。

其他運(yùn)算符

大多數(shù)其它的運(yùn)算符,已經(jīng)在其它的示例中使用過:

運(yùn)算符 名字 描述
() 使用方法 代表調(diào)用一個(gè)方法
[] 訪問 List 訪問 List 中特定位置的元素
. 訪問成員 成員訪問符
?. 條件訪問成員 與上述成員訪問符類似蜈缤,但是左邊的操作對(duì)象不能為 null拾氓,例如 foo?.bar,如果 foo 為 null 則返回 null 劫樟,否則返回 bar

更多關(guān)于 ., ?... 運(yùn)算符介紹痪枫,請(qǐng)參考.

流程控制語(yǔ)句

你可以使用下面的語(yǔ)句來控制 Dart 代碼的執(zhí)行流程:

  • ifelse

  • for 循環(huán)

  • whiledo-while 循環(huán)

  • breakcontinue

  • switchcase

  • assert

使用 try-catchthrow 也能影響控制流,詳情參考異常部分叠艳。

If 和 Else

Dart 支持 if - else 語(yǔ)句奶陈,其中 else 是可選的,比如下面的例子附较。你也可以參考條件表達(dá)式吃粒。

if (isRaining()) {
  you.bringRainCoat();
} else if (isSnowing()) {
  you.wearJacket();
} else {
  car.putTopDown();
}

與 JavaScript 不同的是,Dart 的 if 語(yǔ)句中的條件必須是一個(gè)布爾值拒课,不能是其它類型徐勃。詳情請(qǐng)查閱布爾值

For 循環(huán)

你可以使用標(biāo)準(zhǔn)的 for 循環(huán)進(jìn)行迭代早像。例如:

var message = StringBuffer('Dart is fun');
for (var i = 0; i < 5; i++) {
  message.write('!');
}

在 Dart 語(yǔ)言中僻肖,for 循環(huán)中的閉包會(huì)自動(dòng)捕獲循環(huán)的 索引值 以避免 JavaScript 中一些常見的陷阱。假設(shè)有如下代碼:\

var callbacks = [];
for (var i = 0; i < 2; i++) {
  callbacks.add(() => print(i));
}
callbacks.forEach((c) => c());

上述代碼執(zhí)行后會(huì)輸出 01卢鹦,但是如果在 JavaScript 中執(zhí)行同樣的代碼則會(huì)輸出兩個(gè) 2臀脏。

如果要遍歷的對(duì)象實(shí)現(xiàn)了 Iterable 接口,則可以使用 forEach() 方法冀自,如果不需要使用到索引揉稚,則使用 forEach 方法是一個(gè)非常好的選擇:

candidates.forEach((candidate) => candidate.interview());

像 List 和 Set 等實(shí)現(xiàn)了 Iterable 接口的類還支持 for-in 形式的迭代

var collection = [0, 1, 2];
for (var x in collection) {
  print(x); // 0 1 2
}

While 和 Do-While

while 循環(huán)會(huì)在執(zhí)行循環(huán)體前先判斷條件:

while (!isDone()) {
  doSomething();
}

do-while 循環(huán)則會(huì)先執(zhí)行一遍循環(huán)體 再 判斷條件:

do {
  printLine();
} while (!atEndOfPage());

Break 和 Continue

while (true) {
  if (shutDownRequested()) break;
  processIncomingRequests();
}

使用continue可以跳過本次循環(huán)直接進(jìn)入下一次循環(huán):

for (int i = 0; i < candidates.length; i++) {
  var candidate = candidates[i];
  if (candidate.yearsExperience < 5) {
    continue;
  }
  candidate.interview();
}

上述代碼中的 candidates 如果像 List 或 Set 一樣實(shí)現(xiàn)了 Iterable 接口則可以簡(jiǎn)單地使用下述寫法:

candidates
    .where((c) => c.yearsExperience >= 5)
    .forEach((c) => c.interview());

Switch 和 Case

Switch 語(yǔ)句在 Dart 中使用 == 來比較整數(shù)、字符串或編譯時(shí)常量熬粗,比較的兩個(gè)對(duì)象必須是同一個(gè)類型且不能是子類并且沒有重寫 == 操作符搀玖。枚舉類型非常適合在 Switch 語(yǔ)句中使用。
每一個(gè)非空的 case 子句都必須有一個(gè) break 語(yǔ)句驻呐,也可以???過 continue灌诅、throw 或者 return 來結(jié)束非空 case 語(yǔ)句。

當(dāng)沒有 case 語(yǔ)句匹配時(shí)含末,可以使用 default 子句來匹配這種情況:

var command = 'OPEN';
switch (command) {
  case 'CLOSED':
    executeClosed();
    break;
  case 'PENDING':
    executePending();
    break;
  case 'APPROVED':
    executeApproved();
    break;
  case 'DENIED':
    executeDenied();
    break;
  case 'OPEN':
    executeOpen();
    break;
  default:
    executeUnknown();
}

下面的例子忽略了 case 子句的 break 語(yǔ)句猜拾,因此會(huì)產(chǎn)生錯(cuò)誤:

var command = 'OPEN';
switch (command) {
  case 'OPEN':
    executeOpen();
    // 錯(cuò)誤: 沒有 break

  case 'CLOSED':
    executeClosed();
    break;
}

但是,Dart 支持空的 case 語(yǔ)句答渔,允許其以 fall-through 的形式執(zhí)行关带。

var command = 'CLOSED';
switch (command) {
  case 'CLOSED': // case 語(yǔ)句為空時(shí)的 fall-through 形式。
  case 'NOW_CLOSED':
    // case 條件值為 CLOSED 和 NOW_CLOSED 時(shí)均會(huì)執(zhí)行該語(yǔ)句。
    executeNowClosed();
    break;
}

在非空 case 語(yǔ)句中想要實(shí)現(xiàn) fall-through 的形式宋雏,可以使用 continue 語(yǔ)句配合 lable 的方式實(shí)現(xiàn):

var command = 'CLOSED';
switch (command) {
  case 'CLOSED':
    executeClosed();
    continue nowClosed;
  // 繼續(xù)執(zhí)行標(biāo)簽為 nowClosed 的 case 子句芜飘。

  nowClosed:
  case 'NOW_CLOSED':
    // case 條件值為 CLOSED 和 NOW_CLOSED 時(shí)均會(huì)執(zhí)行該語(yǔ)句。
    executeNowClosed();
    break;
}

每個(gè) case 子句都可以有局部變量且僅在該 case 語(yǔ)句內(nèi)可見磨总。
斷言
在開發(fā)過程中嗦明,可以在條件表達(dá)式為 false 時(shí)使用 - assert(條件, 可選信息); - 語(yǔ)句來打斷代碼的執(zhí)行。你可以在本文中找到大量使用 assert 的例子蚪燕。下面是相關(guān)示例:

// 確保變量值不為 null娶牌。
assert(text != null);

// 確保變量值小于 100。
assert(number < 100);

// 確保這是一個(gè) https 地址馆纳。
assert(urlString.startsWith('https'));

assert 的第二個(gè)參數(shù)可以為其添加一個(gè)字符串消息诗良。

assert(urlString.startsWith('https'),
    'URL ($urlString) should start with "https".');
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市鲁驶,隨后出現(xiàn)的幾起案子鉴裹,更是在濱河造成了極大的恐慌,老刑警劉巖钥弯,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件径荔,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡脆霎,警方通過查閱死者的電腦和手機(jī)总处,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來睛蛛,“玉大人鹦马,你說我怎么就攤上這事【猎海” “怎么了菠红?”我有些...
    開封第一講書人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵第岖,是天一觀的道長(zhǎng)难菌。 經(jīng)常有香客問我,道長(zhǎng)蔑滓,這世上最難降的妖魔是什么郊酒? 我笑而不...
    開封第一講書人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮键袱,結(jié)果婚禮上燎窘,老公的妹妹穿的比我還像新娘。我一直安慰自己蹄咖,他們只是感情好褐健,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般蚜迅。 火紅的嫁衣襯著肌膚如雪舵匾。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,007評(píng)論 1 284
  • 那天谁不,我揣著相機(jī)與錄音坐梯,去河邊找鬼。 笑死刹帕,一個(gè)胖子當(dāng)著我的面吹牛吵血,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播偷溺,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼蹋辅,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了挫掏?” 一聲冷哼從身側(cè)響起晕翠,我...
    開封第一講書人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎砍濒,沒想到半個(gè)月后淋肾,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡爸邢,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年樊卓,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片杠河。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡碌尔,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出券敌,到底是詐尸還是另有隱情唾戚,我是刑警寧澤,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布待诅,位于F島的核電站叹坦,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏卑雁。R本人自食惡果不足惜募书,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望测蹲。 院中可真熱鬧莹捡,春花似錦、人聲如沸扣甲。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至启泣,卻和暖如春媒咳,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背种远。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來泰國(guó)打工涩澡, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人坠敷。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓妙同,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親膝迎。 傳聞我的和親對(duì)象是個(gè)殘疾皇子粥帚,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • 這是16年5月份編輯的一份比較雜亂適合自己觀看的學(xué)習(xí)記錄文檔,今天18年5月份再次想寫文章限次,發(fā)現(xiàn)簡(jiǎn)書還為我保存起的...
    Jenaral閱讀 2,732評(píng)論 2 9
  • Dart重要概念:1芒涡,在變量中可以放置的所有東西都是對(duì)象,而每個(gè)對(duì)象都是類的實(shí)例卖漫。無論數(shù)字费尽、函數(shù)、和null都是對(duì)...
    哥哥是歐巴Vitory閱讀 789評(píng)論 0 1
  • 前言 把《C++ Primer》[https://book.douban.com/subject/25708312...
    尤汐Yogy閱讀 9,506評(píng)論 1 51
  • 此文章是v1.0+時(shí)編寫羊始,年代久遠(yuǎn)旱幼,小心有毒,謹(jǐn)慎食用M晃0芈薄! 一些重要概念 所有的東西都是對(duì)象匀油,所有的對(duì)象都是類的...
    soojade閱讀 10,040評(píng)論 2 27
  • 一個(gè)基本的Dart程序 下面的代碼中使用了很多Dart最基本的特性: 重要概念 所有你能夠賦值給一個(gè)變量的都是一個(gè)...
    YZune閱讀 14,498評(píng)論 2 14