Dart 語法學習筆記一


Dart 是谷歌于2011年10月10日發(fā)布一門開源編程語言(日子挑的不錯)。2018年之前一直處于蟄伏狀態(tài),flutter 之后聲名雀起,一發(fā)不可收拾!

Dart 的存在的存在的意義是什么呢?看一下官網(wǎng)的概述:

Dart is a client-optimized language for developing fast apps on any platform. Its goal is to offer the most productive programming language for multi-platform development, paired with a flexible execution runtime platform for app frameworks.

廢話說完了,進入正題!

Hello Dart

怎么能少得了 Hello World !

// 程序入口函數(shù)
void main() {
  // 函數(shù)調(diào)用
  printHelloWorld();
}

// 定義函數(shù) printHelloWorld
void printHelloWorld() {
 // 實現(xiàn),打印 Hello World
  print("Hello World !");
}

如上,一個簡單的 Hello World 就寫完了。可以自己打開 DartPad 進行練手!
Dart 語法學習的過程中均可在其上進行練習,灰常方便!

Dart 語言特點

Dart 語言具有以下特點:
0、編譯型;
1、強類型(Dart 2 才是);
2、面向?qū)ο螅磺薪詫ο螅瑪?shù)字、函數(shù)、null 都是對象;

語法

變量
使用關(guān)鍵字 var 進行變量的聲明。

// 聲明一個字符串變量 name 并賦值 Yuri
var  name = "Yuri";
// 聲明一個變量 temperature 并賦值 35.0
var temperature = 35.0;

由于 Dart 有類型推斷機制,name 會被自動判斷為 String 類型。
也可以使用類型顯式的聲明一個變量:

String name = "Yuri";
double temperature = 28.5;

還可以使用 dynamicObject 聲明一個變量。dynamicObject 的變量可以在后期改變賦值的類型,而 Var 聲明的變量則不可以。 dynamic 這個特性與 Objective-C 中的 id 作用很像. dynamic 的這個特點使得我們在使用它時格外需要注意,因為很容易引入運行時錯誤。

dynamic name = "Yuri";
Object temperature = 28.5;
print("$name, $temperature");
// 打印結(jié)果:Yuri, 28.5

name = 28.5;
temperature = "Yuri";
print("$name, $temperature");
// 打印結(jié)果:28.5, Yuri

常量
使用關(guān)鍵字 finalconst 聲明一個常量。

// 使用 final 聲明一個 sex 的常量
final sex = "male";
// 使用 const 聲明一個 nickName 的常量
const nickName = "Kitty";

使用 finalConst 聲明的常量的值不能被修改。

finalconst 的區(qū)別在哪呢?
const 定義的常量在編譯時就已經(jīng)固定,final 定義的常量則在第一次使用時才被初始化。

Dart 內(nèi)建類型

Number
Number 有兩種類型 intdouble

// 定義一個 int 類型變量
int x = 1;
// 定義一個 double 類型變量
double y = 3.14;

int 整數(shù)值不大于64位, 具體取決于平臺。 在 Dart VM 上, 值的范圍從 -263 到 263 - 1. Dart 被編譯為 JavaScript 時,使用 JavaScript numbers, 值的范圍從 -253 到 253 - 1.
double: 64位(雙精度)浮點數(shù),依據(jù) IEEE 754 標準。

String
Dart 字符串是一組 UTF-16 單元序列。字符串通過單引號雙引號創(chuàng)建。

var s1 = 'Single quotes work well for string literals.';
var s2 = "Double quotes work just as well.";
var s3 = 'It\'s easy to escape the string delimiter.';
var s4 = "It's even easier to use the other delimiter.";

字符串可以通過${expression} 的方式內(nèi)嵌表達式。 如果表達式是一個標識符,則{} 可以省略。

var s = 'string interpolation';
print("Dart has $s, which is very handy.");

在 Dart 中通過調(diào)用就對象的 toString() 方法來得到對象相應的字符串。

String oneAsString = 1.toString();
assert(oneAsString == '1');

String piAsString = 3.14159.toStringAsFixed(2);
assert(piAsString == '3.14');

可以使用 + 運算符來把多個字符串連接為一個,也可以把多個字面量字符串寫在一起來實現(xiàn)字符串連接。

var s1 = 'String '
    'concatenation'
    " works even over line breaks.";
print(s1);
// 打印結(jié)果: String concatenation works even over line breaks.

var s2 = 'The + operator ' + 'works, as well.';
print(s2);
// 打印結(jié)果:The + operator works, as well.

Boolean
bool,表示布爾值,有 truefalse 兩個值。

bool isSunny = true;
bool isRainy = false;

List (也被稱為 Array)
List 表示有序集合。

// 定義一個 整形 的數(shù)組字面量
var list = [1, 2, 3];

// 獲取數(shù)組長度
var length = list.length;

// 訪問數(shù)組元素. List 元素的下標也是從 0 開始的
var secondValue = list[1];

Map
通常來說, Map 是用來關(guān)聯(lián) keys 和 values 的對象。

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

var nobleGases = {
  2: 'helium',
  10: 'neon',
  18: 'argon',
};

也可以使用 Map 的構(gòu)造函數(shù)創(chuàng)建對象。

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 添加一個 key-value

gifts["sixth"] = "cake";

訪問 Map 中的 value

var sixthGift = gifts["sixth"];
assert(sixthGift == "cake");

Set
Set 表示無序元素的集合,集合內(nèi)元素唯一。

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

創(chuàng)建一個空集

var names = <String>{};

向 set 中添加元素

names.add("1");
names.addAll({"2", "3"});

Rune (用于在字符串中表示 Unicode 字符)
Dart 字符串是一系列 UTF-16 編碼單元,即每個字符占 16 位, 而 Unicode 則是 32 位的,因此 Dart 字符串中表示 32 位 Unicode 值需要特殊語法支持。

Runes input = new Runes(
      '\u2665  \u{1f605}  \u{1f60e}  \u{1f47b}  \u{1f596}  \u{1f44d}');
print(new String.fromCharCodes(input));

Symbol
一個 Symbol 對象表示 Dart 程序中聲明的運算符或者標識符。 你也許永遠都不需要使用 Symbol ,但要按名稱引用標識符的 API 時, Symbol 就非常有用了。 因為代碼壓縮后會改變標識符的名稱,但不會改變標識符的符號。 通過字面量 Symbol ,也就是標識符前面添加一個 # 號,來獲取標識符的 Symbol 。

#radix
#bar

Symbol 字面量是編譯時常量。

函數(shù)

Dart 中一切皆對象。函數(shù)也是對象,其對應的類型為 Function

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

在 Effective Dart 中推薦 公共API中聲明類型, 但是省略了類型聲明,函數(shù)依舊是可以正常使用的

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

如果函數(shù)中只有一句表達式,可以使用簡寫語法:

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

=> expr 語法是 { return expr; } 的簡寫。 => 符號 有時也被稱為 箭頭 語法。

在 Dart 語言中,函數(shù)是一等對象(難道還有二等,三等?)。
函數(shù)可以作為另一個函數(shù)的參數(shù),同時也可以把函數(shù)賦值給一個變量。

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

var list = [1, 2, 3];
// 將 printElement 函數(shù)作為參數(shù)傳遞。
list.forEach(printElement);

// 將函數(shù)作為值賦給變量
var loudify = (msg) => '!!! ${msg.toUpperCase()} !!!';
assert(loudify('hello') == '!!! HELLO !!!');

匿名函數(shù)
一般情況下函數(shù)是有名字的,把沒有名字的函數(shù)叫做匿名函數(shù)
匿名函數(shù)有時也被稱為 lambda 或者 closure
在將函數(shù)作為值賦值給變量時,我們用的就是一個匿名函數(shù)。

可選參數(shù)
可選參數(shù)分命名參數(shù)位置參數(shù)。一個參數(shù)只能選擇其中一種進行修飾。

命名可選參數(shù)

/// Sets the [bold] and [hidden] flags ...
void enableFlags({bool bold, bool hidden}) {
  ...
}

調(diào)用

enableFlags(bold: true, hidden: false);

命名可選參數(shù)可以用 @required 進行修飾,表示在函數(shù)調(diào)用時該參數(shù)不可缺少。

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

此時 Scrollbar 是一個構(gòu)造函數(shù), 當 child 參數(shù)缺少時,分析器會提示錯誤。

位置可選參數(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ù)
在定義函數(shù)時,我們可以給參數(shù)一個默認值。

/// 設(shè)置 [bold] 和 [hidden] 標志 ...
void enableFlags({bool bold = false, bool hidden = false}) {
  ...
}

// bold 值為 true; hidden 值為 false.
enableFlags(bold: true);

運算符

算術(shù)運算符

操作符 功能
+
-
*
/
~/ 除法取整
% 模(余數(shù))

除了上面的基本的算術(shù)運算符,Dart 同樣也支持帶有前綴的自增和自減運算符。
++exprexpr++--exprexpr--

/// 基本操作運算符示例
assert(2 + 3 == 5);
assert(2 - 3 == -1);
assert(2 * 3 == 6);
assert(5 / 2 == 2.5); // 結(jié)果是雙浮點型
assert(5 ~/ 2 == 2); // 結(jié)果是整型
assert(5 % 2 == 1); // 余數(shù)

/// 自增自減運算符示例
var a, b;

a = 0;
b = ++a; // a自加后賦值給b。
assert(a == b); // 1 == 1

a = 0;
b = a++; // a先賦值給b后,a自加。
assert(a != b); // 1 != 0

a = 0;
b = --a; // a自減后賦值給b。
assert(a == b); // -1 == -1

a = 0;
b = a--; // a先賦值給b后,a自減。
assert(a != b); // -1 != 0

關(guān)系運算符

操作符 功能
== 等于
!= 不等于
> 大于
>= 大于等于
< 小于
<= 小于等于

比較簡單,不再示例。

類型判定運算符

操作符 功能
as 類型轉(zhuǎn)化
is 類型判斷(True if the object has the specified type)
is! 類型判斷(False if the object has the specified type)

is 比較好理解,是就返回 true,不是就返回 false;
is! 意義則相反,不是就返回 true,是就返回 false;
個人感覺大部分情況下,is 就夠了!

賦值運算符

= 是基本的賦值運算符,通過與其它操作符的組合,會產(chǎn)生許多其它的復合賦值運算符。如下

= -= /= %= >>= ^=
+= *= ~/= <<= &= |=

比較簡單,不再示例。

邏輯運算符

操作符 含義
&&
||
!

不再示例。

按位和移位運算符

操作符 含義
& 按位與(AND)
| 按位或(OR)
^ 按位異或(XOR)
~expr 取反(Unary bitwise complement (0s become 1s; 1s become 0s))
<< 左移(Shift left)
>> 右移(Shift right)

條件表達式

condition ? expr1 : expr2
如果條件為 true, 執(zhí)行 expr1 (并返回它的值): 否則, 執(zhí)行并返回 expr2 的值。

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

expr1 ?? expr2
如果 expr1 是 non-null, 返回 expr1 的值; 否則, 執(zhí)行并返回 expr2 的值。

String playerName(String name) => name ?? 'Guest';

級聯(lián)運算符

級聯(lián)運算符 .. 可以實現(xiàn)對同一個對像進行一系列的操作。除了調(diào)用函數(shù), 還可以訪問同一對象上的字段屬性。

querySelector('#confirm') // 獲取對象。
  ..text = 'Confirm' // 調(diào)用成員變量。
  ..classes.add('important')
  ..onClick.listen((e) => window.alert('Confirmed!'));

這個運算符在 iOS 開發(fā)過程中沒有遇到過,應該是 Dart 特胡的語法糖。

其它運算符

Operator Name Meaning
() Function application Represents a function call
[] List access Refers to the value at the specified index in the list
. Member access Refers to a property of an expression; example: foo.bar selects property bar from expression foo
?. Conditional member access Like ., but the leftmost operand can be null; example: foo?.bar selects property bar from expression foo unless foo is null (in which case the value of foo?.bar is null)

控制流程語句

if ... else ...

注意:條件語句必須是布爾值

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

for loops

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

while and do-while loops

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

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

break and continue

break: 停止程序循環(huán)。
continue:跳過當次循環(huán)。

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

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

switch and case

注意:正常情況下,case 中的 break 不可省略。

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();
}

assert

如果 assert 語句中的布爾條件為 false , 那么正常的程序執(zhí)行流程會被中斷。

// 確認變量值不為空。
assert(text != null);

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

// 確認 URL 是否是 https 類型。
assert(urlString.startsWith('https'));

異常處理

Dart 可以拋出和捕獲異常。
throw
throw 用于拋出異常。
當函數(shù)執(zhí)行過程中出現(xiàn)了異常,可以通過 throw 將異常拋出。異常可以是 Exception 或 Error,或其它任何非 null 對象。當拋出異常時,程序也將會被終止。

throw FormatException('Expected at least 1 section');

以下示例拋出了一條字符串消息

throw 'Out of llamas!';

catch
捕獲異常可以避免異常繼續(xù)傳遞.

try {
  breedMoreLlamas();
} on OutOfLlamasException {
  buyMoreLlamas();
}

通過指定多個 catch 語句,可以處理可能拋出多種類型異常的代碼。 與拋出異常類型匹配的第一個 catch 語句處理異常。 如果 catch 語句未指定類型, 則該語句可以處理任何類型的拋出對象:

try {
  breedMoreLlamas();
} on OutOfLlamasException {
  // 一個特殊的異常
  buyMoreLlamas();
} on Exception catch (e) {
  // 其他任何異常
  print('Unknown exception: $e');
} catch (e) {
  // 沒有指定的類型,處理所有異常
  print('Something really unknown: $e');
}

如上述代碼所示,捕獲語句中可以同時使用 oncatch ,也可以單獨分開使用。 使用 on 來指定異常類型, 使用 catch 來 捕獲異常對象。

catch() 函數(shù)可以指定1到2個參數(shù), 第一個參數(shù)為拋出的異常對象, 第二個為堆棧信息 ( 一個 StackTrace 對象 )。

try {
  // ···
} on Exception catch (e) {
  print('Exception details:\n $e');
} catch (e, s) {
  print('Exception details:\n $e');
  print('Stack trace:\n $s');
}

如果僅需要部分處理異常, 那么可以使用關(guān)鍵字 rethrow 將異常重新拋出。

void misbehave() {
  try {
    dynamic foo = true;
    print(foo++); // Runtime error
  } catch (e) {
    print('misbehave() partially handled ${e.runtimeType}.');
    rethrow; // Allow callers to see the exception.
  }
}

void main() {
  try {
    misbehave();
  } catch (e) {
    print('main() finished handling ${e.runtimeType}.');
  }
}

finally
不管是否拋出異常, finally 中的代碼都會被執(zhí)行。 如果 catch 沒有匹配到異常, 異常會在 finally 執(zhí)行完成后,再次被拋出:

try {
  breedMoreLlamas();
} finally {
  // Always clean up, even if an exception is thrown.
  cleanLlamaStalls();
}

任何匹配的 catch 執(zhí)行完成后,再執(zhí)行 finally :

try {
  breedMoreLlamas();
} catch (e) {
  print('Error: $e'); // Handle the exception first.
} finally {
  cleanLlamaStalls(); // Then clean up.
}

Dart 語法學習筆記二

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。