dart是一種真正面向?qū)ο蟮恼Z言,所以函數(shù)也是對象,并且有一個類型腐碱、Function
。這意味著函數(shù)可以分配給變量或者作為參數(shù)傳遞給其他函數(shù)掉弛。你也可以調(diào)用Dart類的實例症见,就像它是一個函數(shù)一樣喂走。
下面是一個實現(xiàn)函數(shù)的例子:
bool isNoble(int atomicNumber) {
return _nobleGases[atomicNumber] != null;
}
雖然Effective Dart(作者推薦:dart的有效寫法)推薦公共API的類型注釋,但是如果省略以下類型谋作,該函數(shù)仍然有效
isNoble(atomicNumber) {
return _nobleGases[atomicNumber] != null;
}
對于只包含一個表達式的函數(shù)芋肠,可以使用速記語法:
bool isNoble(int atomicNumber) => _nobleGases[atomicNumber] != null;
=> expr
語法是{return expr;}
遵蚜。=>
符號有時被稱為箭頭語法业栅。
注意:只有表達式(而不是語句!)可以存在于箭頭
( => )
和分號(;)
之間谬晕。 例如,你不能使用if語句携取,但可以用條件表達式攒钳。
函數(shù)可以有兩種類型的參數(shù):必需參數(shù)和可選參數(shù)。首先列出所需參數(shù)雷滋,然后列出任何可選參數(shù)不撑。命名的可選參數(shù)也可以標記為@required
。
可選參數(shù)
可選參數(shù)可以是位置參數(shù)晤斩,也可以是命名參數(shù)焕檬,但不能同時是位置參數(shù)和命名參數(shù)。
1.可選命名參數(shù)
調(diào)用函數(shù)時澳泵,可以使用paramName : value
指定命名參數(shù)实愚。例如:
enableFlags(bold: true, hidden: false);
定義函數(shù)時,使用{ param 1兔辅,param 2腊敲,... }指定命名參數(shù):
/// Sets the [bold] and [hidden] flags ...
void enableFlags({bool bold, bool hidden}) {...}
Flutter
實例創(chuàng)建表達式可能會變得復雜,因此Widget
構(gòu)造函數(shù)專門使用命名參數(shù)维苔。這使得實例創(chuàng)建表達式更容易閱讀碰辅。
你可以用@required
注釋任何Dart代碼中的命名參數(shù)(不僅僅是Flutter
),以指示它是必需的參數(shù)介时。例如:
const Scrollbar({Key key, @required Widget child})
當Scrollbar
被構(gòu)建時没宾,分析器會在缺少child
參數(shù)時報錯。
Require
被定義在meta包里沸柔。要么直接導入package:meta/meta.dart
循衰,要么導入另一個導出meta
包,如Flutter的package:flutter/material.dart.
2.可選位置參數(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;
}
這里有一個調(diào)用這個函數(shù)的例子羹蚣,沒有可選參數(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');
3.默認參數(shù)值
函數(shù)可以使用=
為命名參數(shù)和位置參數(shù)定義默認值。默認值必須是編譯時常量乱凿。如果未提供默認值顽素,則默認值為null咽弦。
下面是為命名參數(shù)設(shè)置默認值的示例:
///設(shè)置bold默認值為true,實質(zhì)hidden'默認值為false
void enableFlags({bool bold = false, bool hidden = false}) {...}
// bold為true; hidden為 false.
enableFlags(bold: true);
下一個示例顯示如何設(shè)置位置參數(shù)的默認值:
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');
你也可以將集合(lists)
或映射(maps)
作為默認值傳遞胁出。下面的示例定義了一個函數(shù)doStuff()
型型,該函數(shù)指定了一個默認的集合
來放置list
參數(shù)和默認的映射
來放置gitfts
的參數(shù)
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');
}
主函數(shù)
每個應(yīng)用程序都必須有一個頂級main()
函數(shù),作為應(yīng)用程序的入口點全蝶。main()
函數(shù)返回void闹蒜,并具有可選的List<String>
作為參數(shù)。
下面是一個web應(yīng)用程序的main()
函數(shù)示例:
void main() {
querySelector('#sample_text_id')
..text = 'Click me!'
..onClick.listen(reverseText);
}
注意:..
前面代碼中的語法稱為級聯(lián)抑淫。使用級聯(lián)绷落,可以對單個對象的成員執(zhí)行多個操作。
下面是接受參數(shù)的命令行應(yīng)用程序的main ( )函數(shù)的示例:
// Run the app like this: dart args.dart 1 test
void main(List<String> arguments) {
print(arguments);
assert(arguments.length == 2);
assert(int.parse(arguments[0]) == 1);
assert(arguments[1] == 'test');
}
您可以使用args library
來定義和解析命令行參數(shù)始苇。
方法作為一等對象
你可以將函數(shù)作為參數(shù)傳遞給另一個函數(shù)砌烁。例如:
void printElement(int element) {
print(element);
}
var list = [1, 2, 3];
// Pass printElement as a parameter.
list.forEach(printElement);
你也可以將函數(shù)分配給變量,例如:
var loudify = (msg) => '!!! ${msg.toUpperCase()} !!!';//匿名函數(shù)
assert(loudify('hello') == '!!! HELLO !!!');
匿名函數(shù)
大多數(shù)函數(shù)都是命名的催式,例如main()
或printElement()
函喉。你也可以創(chuàng)建一個沒有名字函數(shù)(匿名函數(shù)),有時也可以創(chuàng)建lambda或閉包荣月。你可以將匿名函數(shù)分配給變量管呵,因此你可以這樣,例如:可以從集合中添加或刪除它哺窄。
匿名函數(shù)看起來類似于命名函數(shù)——零個或多個參數(shù)捐下,括號中用逗號和可選類型注釋隔開。
下面的代碼塊包含函數(shù)的主體:
([[Type] param1[, …]]) {
codeBlock;
};
下面的示例使用非類型化參數(shù)item
定義了一個匿名函數(shù)堂氯。為列表中的每個項目調(diào)用的函數(shù)會打印一個字符串蔑担,其中包含指定索引處的值。
var list = ['apples', 'bananas', 'oranges'];
list.forEach((item) {
print('${list.indexOf(item)}: $item');
});
--------------------------------------------------
0: apples
1: bananas
2: oranges
如果函數(shù)只包含一條語句咽白,可以使用箭頭符號來縮短它啤握。
list.forEach(
(item) => print('${list.indexOf(item)}: $item'));
--------------------------------------------------
0: apples
1: bananas
2: oranges
作用域
dart是一種詞匯作用域的語言,這意味著變量的作用域是由代碼的布局靜態(tài)決定的晶框。
下面是一個嵌套函數(shù)的例子排抬,每個作用域級別內(nèi)都有變量:
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)的變量济丘,就算該函數(shù)是在其原始作用域之外使用的在讶。
函數(shù)可以關(guān)聯(lián)周圍作用域中定義的變量唆缴。在接下來的例子中,makeAdder()
獲取變量addBy
东抹。無論返回的函數(shù)去哪里帕识,它都會記住addBy
潜腻。
/// Returns a function that adds [addBy] to the
/// function's argument.
Function makeAdder(num addBy) {
return (num 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);
}
測試函數(shù)是否相等
下面是測試頂級函數(shù)、靜態(tài)方法和實例方法是否相等的示例:
void foo() {} // 頂級函數(shù)
class A {
static void bar() {} // 靜態(tài)函數(shù)
void baz() {} // 對象函數(shù)
}
void main() {
var x;
// 對比頂級函數(shù)
x = foo;
assert(foo == x);
// 對比靜態(tài)函數(shù)
x = A.bar;
assert(A.bar == x);
// 對比對象函數(shù)
var v = A(); // Instance #1 of A
var w = A(); // Instance #2 of A
var y = w;
x = w.baz;
// 這些閉包指向同一實例 (#2),
// 因此他們是相等的
assert(y.baz == x);
// 這些閉包指向不同的實例
// 因此他們是相等的
assert(v.baz != w.baz);
}
返回值
所有函數(shù)都返回值卡睦。如果未指定返回值宴胧,則語句返回null
;隱式附加到函數(shù)體表锻。
foo() {}
assert(foo() == null);
PS:本文
整理
自官方文檔恕齐,若有發(fā)現(xiàn)問題請致郵 caoyanglee92@gmail.com