
此文是致力于幫助你更好地理解并高效使用 Dart 語言系列文集的第一篇。
Dart(2.0+) 和 Flutter 都是相對較新的技術(shù),每天都有大量的人加入開發(fā)者社區(qū),他們參考的很多示例代碼仍在照搬其他語言中的代碼模式,而未使用 Dart 提供的完整運(yùn)算符集。
1、 ?:(三目運(yùn)算符)
三目運(yùn)算符已經(jīng)存在于許多語言中,它允許將 if-else 語句中兩條可能的執(zhí)行路徑改寫為更簡潔的形式。
比如以下代碼:

可以寫成:

三元運(yùn)算符的結(jié)構(gòu)如下所示:
condition ? (statement if true) : (statement if false);
如果涉及到返回值,return只需要加在開頭,而不是在子語句中:
return condition ? (statement if true) : (statement if false);
而不是
condition ? return (statement if true) : return (statement if false);
2、 ??

?? 是 null 檢查符。在上例中,如果 person.name 為 null,則 name 被賦值為 "John Doe"。這大大簡化了代碼,減少了先檢查 name 是否為空,再決定如何賦值的邏輯(如下圖的代碼對比)。

?? 運(yùn)算符無需大量檢查代碼,能更加容易地處理意外的 null 值。
3、?.
設(shè)想一個叫 Point 的類,它有 x 和 y 成員:
classPoint {
int x;
int y;
Point(this.x, this.y);
}
如果我們有一個未初始化的 Point 對象,并且試圖訪問內(nèi)部成員,它不會返回 null,而是直接拋出一個錯誤。
比如:
Point point;
print(point.x);
將拋出:
Unhandled exception:
NoSuchMethodError: The getter 'x'was called on null.
Receiver: null
Tried calling: x
相反,如果它只返回 null,我們可以就很容易地處理和解決未初始化的問題。
同樣,簡單的解決方案是使用 if-else:

這看起來不錯,但很容易遇到限制。以我們解析 JSON 為例,它可能有很多層嵌套的數(shù)據(jù)。比如:
pages[0].contributors[0].authorDetails.basicInfo.firstName
程序中任何錯誤都可能導(dǎo)致這個調(diào)用鏈中某個部分為 null。例如說,authorDetails 可能根本沒有 basicInfo 字段。
在這些情況下,判空檢查是一場噩夢,只要這些字段中的一個字段為空(firstName 除外,因?yàn)樗亲詈笠粋€字段),則整個調(diào)用都會失敗。
那我們該怎么辦?沒有簡單的 if-else 或三目運(yùn)算解決方案。而且在一個完美的系統(tǒng)里,這個錯誤根本不應(yīng)該存在,但我們并不總會有完美的系統(tǒng)和 API。此時(shí),?. 運(yùn)算符派上用場了。
這個運(yùn)算符大致表述為:“如果對象不為 null,則訪問內(nèi)部字段,否則返回 null?!?/p>
因此,即使我們前面的 point.x 示例也會拋出 null 而不是錯誤。這使我們的工作變得更加容易,并且可以簡單地使用上一個運(yùn)算符來處理 null 錯誤。

這里如果 point 未初始化,訪問 x 將返回 null 而不是拋出錯誤。然后這個 null 被 null 檢查運(yùn)算符(??)捕獲,該運(yùn)算符將 0 賦值給變量 x。
類似地,我們可以將前面的示例修改為:
pages[0]?.contributors[0]?.authorDetails?.basicInfo?.firstName ?? "N/A";
現(xiàn)在,如果表達(dá)式任意部分為 null,則將返回 "N/A"。
4、??=
??= 可簡單的理解為:“如果表達(dá)式左側(cè)為空,則執(zhí)行賦值”。即只有當(dāng)變量為 null 時(shí)才會被賦值。

可以避免給變量做不必要的重新賦值。
5、=>
=> 在 Dart 中被稱為胖箭頭 (fat arrow) 符號。它有兩種不同的用途,兩者都與定義函數(shù)有關(guān)。
首先將其作為返回某物的簡寫,=> x 表示 { return x;}

此外該運(yùn)算符也適用于單個語句,即使不返回任何內(nèi)容。

請注意,如果返回類型是 void,則即使是 => s 也不會返回任何東西。
6、..(級聯(lián)符號)
級聯(lián)表示法是一種修改對象屬性的簡單方式,通常用于在創(chuàng)建對象而不是獲取該對象的引用時(shí)逐個修改其屬性。
我們要舉的第一個例子還是之前的 Point 類。假設(shè)我們首先需要初始化類,然后設(shè)置x和y屬性。你可能會想到這么做:
Point p = Point();
p.x= 3;
p.y= 6;
級聯(lián)表示法為我們提供了一種更簡單的方法,無需再次使用對象來設(shè)置屬性。

需要注意的,如果我們只是使用 . 運(yùn)算符,第一行不會返回一個 Point 對象。
級聯(lián)符號的主要作用是:
1. 將 Point 對象創(chuàng)建為默認(rèn)值;
2. 通過級聯(lián)操作更改任何受影響的屬性;
3. 返回原始對象(此處為 Point 實(shí)例);
這在需要設(shè)置大量屬性時(shí)非常有用,例如在 Builder 模式中。Dart 文檔中有個很好的例子:

7、~/
Dart 也有幾個用于加速算術(shù)運(yùn)算的運(yùn)算符。~/ 運(yùn)算符返回除法計(jì)算結(jié)果的整數(shù)部分。

以上介紹的這些運(yùn)算符簡化了代碼并減少了 Bug 的發(fā)生。
8、追加:展開運(yùn)算符 ...(尚未發(fā)布)
... 是一個還在討論中的運(yùn)算符,用作 Dart 中集合 (collections) 的展開運(yùn)算符。
List 可以很方便地被展開:

這段代碼直接將 demoList 的元素展開添加至列表中,而不是將其作為 List 對象添加。
來源:https://medium.com/flutter-community/simple-and-bug-free-code-with-dart-operators-2e81211cecfe
作者:Deven Joshi
編譯:碼王爺