爲了使文件前面部分保持整潔,咱們規定了關鍵字出現順序的規則。每一個「部分」應該使用空行分割。html
要把 「dart:」 導入語句放到其餘導入語句以前。編程
要把 「package:」 導入語句放到項目相關導入語句以前。bash
import 'dart:async';
import 'dart:html';
import 'package:bar/bar.dart';
import 'package:foo/foo.dart';
import 'package:bar/bar.dart';
import 'package:foo/foo.dart';
import 'util.dart';
複製代碼
推薦 把外部擴展 「package:」 導入語句放到其餘語句以前。async
若是你使用了多個 「package:」 導入語句來導入本身的包以及其餘外部擴展包,推薦將本身的包分開放到一個額外的部分。函數式編程
import 'package:bar/bar.dart';
import 'package:foo/foo.dart';
import 'package:my_package/util.dart';
複製代碼
要 把導出(export)語句做爲一個單獨的部分放到全部導入語句以後。函數
import 'src/error.dart';
import 'src/foo_bar.dart';
export 'src/error.dart';
複製代碼
在 Dart 中,未初始化的變量擁有一個默認的初始化值:null。即使數字也是如此,由於在 Dart 中一切皆爲對象,數字也不例外。ui
int lineCount;
assert(lineCount == null);
複製代碼
在Dart中用var聲明一個變量後,Dart在編譯時會根據第一次賦值數據的類型來推斷其類型,編譯結束後其類型就已經被肯定。atom
Object 是Dart全部對象的根基類,也就是說全部類型都是Object的子類(包括Function和Null),因此任何類型的數據均可以賦值給Object聲明的對象. dynamic與var同樣都是關鍵詞,聲明的變量能夠賦值任意對象。 而dynamic與Object相同之處在於,他們聲明的變量能夠在後期改變賦值類型。spa
dynamic t;
Object x;
t = "hi world";
x = 'Hello Object';
//下面代碼沒有問題
t = 1000;
x = 1000;
複製代碼
dynamic與Object不一樣的是,dynamic聲明的對象編譯器會提供全部可能的組合, 而Object聲明的對象只能使用Object的屬性與方法, 不然編譯器會報錯。代碼規範
dynamic的這個特性與Objective-C中的id做用很像. dynamic的這個特色使得咱們在使用它時須要格外注意,這很容易引入一個運行時錯誤.
若是您從未打算更改一個變量,那麼使用 final 或 const,不是var,也不是一個類型。 一個 final 變量只能被設置一次,二者區別在於:const 變量是一個編譯時常量,final變量在第一次使用時被初始化。被final或者const修飾的變量,變量類型能夠省略,如:
//能夠省略String這個類型聲明
final str = "hi world";
//final String str = "hi world";
const str1 = "hi world";
//const String str1 = "hi world";
複製代碼
Dart是一種真正的面向對象的語言,因此即便是函數也是對象,而且有一個類型Function。這意味着函數能夠賦值給變量或做爲參數傳遞給其餘函數,這是函數式編程的典型特徵。
Dart函數聲明若是沒有顯式聲明返回值類型時會默認當作dynamic處理,注意,函數返回值沒有類型推斷。
bool isNoble(int atomicNumber) {
return _nobleGases[atomicNumber] != null;
}
typedef bool CALLBACK();
//不指定返回類型,此時默認爲dynamic,不是bool
isNoble(int atomicNumber) {
return _nobleGases[atomicNumber] != null;
}
void test(CALLBACK cb){
print(cb());
}
//報錯,isNoble不是bool類型
test(isNoble);
複製代碼
級聯運算符(..)可讓你在同一個對象上連續調用多個對象的變量或方法。
好比下面的代碼:
querySelector('#confirm') // 獲取對象 (Get an object).
..text = 'Confirm' // 使用對象的成員 (Use its members).
..classes.add('important')
..onClick.listen((e) => window.alert('Confirmed!'));
複製代碼
第一個方法 querySelector 返回了一個 Selector 對象,後面的級聯操做符都是調用這個 Selector 對象的成員並忽略每一個操做的返回值。
上面的代碼至關於:
var button = querySelector('#confirm');
button.text = 'Confirm';
button.classes.add('important');
button.onClick.lis
複製代碼
ten((e) => window.alert('Confirmed!')); 級聯運算符能夠嵌套,例如:
final addressBook = (AddressBookBuilder()
..name = 'jenny'
..email = 'jenny@example.com'
..phone = (PhoneNumberBuilder()
..number = '415-555-0100'
..label = 'home')
.build())
.build();
複製代碼
使用類的成員 對象的 成員 由函數和數據(即 方法 和 實例變量)組成。方法的 調用 要經過對象來完成,這種方式能夠訪問對象的函數和數據。
使用(.)來訪問對象的實例變量或方法:
var p = Point(2, 2);
// 爲實例變量 y 賦值。
p.y = 3;
// 獲取 y 的值。
assert(p.y == 3);
// 調用變量 p 的 distanceTo() 方法。
num distance = p.distanceTo(Point(4, 4));
複製代碼
使用 ?. 代替 . 能夠避免由於左邊表達式爲 null 而致使的問題:
// If p is non-null, set its y value to 4.
// 若是 p 爲非空則將其屬性 y 的值設爲 4
p?.y = 4;
複製代碼
使用構造函數 可使用 構造函數 來建立一個對象。構造函數的命名方式能夠爲 類名 或 類名.標識符 的形式。例以下述代碼分別使用 Point() 和 Point.fromJson() 兩種構造器建立了 Point 對象:
var p1 = Point(2, 2);
var p2 = Point.fromJson({'x': 1, 'y': 2});
複製代碼
如下代碼具備相同的效果,可是構造函數名前面的的 new 關鍵字是可選的:
var p1 = new Point(2, 2);
var p2 = new Point.fromJson({'x': 1, 'y': 2});
複製代碼
從 Dart 2 開始,new 關鍵字是可選的。
複製代碼
獲取對象的類型 可使用 Object 對象的 runtimeType 屬性在運行時獲取一個對象的類型,該對象類型是 Type 的實例。
print('The type of a is ${a.runtimeType}');
複製代碼