前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Dart 学习之开发语言概览,带思维导图(一)

Dart 学习之开发语言概览,带思维导图(一)

作者头像
siberiawolf
发布2020-03-24 17:15:51
1.7K0
发布2020-03-24 17:15:51
举报
文章被收录于专栏:前端修炼之路前端修炼之路

之前在学习flutter,本以为自己可以轻松上手掌握dart,结果发现经常有不懂的语法。所以决定踏踏实实的学习一遍dart。网上有很多相关学习资料.我主要从官网来学习,然后又找了一个视频来补充学习。

文章中涉及的代码,可以从我的Github「https://github.com/siberiawolf/dart_study」上找到。

  • 第一遍先看中文文档。毕竟母语是汉语,有利于快速了解。大概掌握自己哪里是之前就会的知识,哪里是新知识。这一遍只看,不进行代码编写。
  • 制作思维导图。在看第一遍的时候,可以用思维导图制作一个清晰的脉络图。也不需要太复杂,只需要将每个大标题、小标题添加上就行。等接下来再去补充。
  • 第二遍就看英文文档。因为第一遍的时候,对文档已经都有印象了,再看英文文档就会比较容易。主要是为了加强自己的英文阅读的能力,这样看得多了,慢慢也就记得多了。
  • 第二遍的时候,遇到不会的生单词,或者高频的单词,记下来,扩大自己的词汇量。就算现在记不住,也先混个脸熟。
  • 第二遍还要进行代码的演练。光看文档的话,我可没有那么强的天赋,能全都理解,毕竟文档只是给出了部分代码示例,或者说是伪代码。所以这一遍将文档中所涉及的代码全部进行一遍演练。
  • 第二遍的时候,还要顺手做两件事情。其中一件就是补充之前做的思维导图,将其完整化。另一件就是,整理一下学习笔记,也就是现在写的这篇笔记。笔记的内容主要记录自己的学习内容即可。
  • 第三遍,观看视频。这最后一遍,就是查漏补缺,有时候文档里面没有的,在视频中还能涉及不少,及时补充。另外视频最重要的一点,就是有些地方看文档、写代码并没有明白,视频中刚好涉及了,稍微一听,也就明白了。当然了,视频比较长,只要是之前学过了,就可以跳步看。

其实这样学下来的话,是比较耗时间的,但是我想还是扎实一下基础吧,磨刀不误砍柴工。往往有时候做项目的话,遇到一些细节,就会模棱两可,含糊不清。甚至有时候看到一块代码,并没有接触过,然后去百度、查文档,虽然当时有印象了,但知识并不系统。

环境搭建

1. 安装Dart SDK

我的电脑是Mac系统,所以需要安装Homebrew。这里我遇到的问题是始终下载失败。最后才下载成功。

接着按照官网给出的示例,安装dart。

最后在终端中输入dart --version显示dart版本号就说明安装成功了。

dart安装成功

2. 配置编辑器的Dart插件

Dart环境我使用的是VS Code,非常简单,只需要安装Dart的插件即可。

  • Code Runner: 是在VS Code中运行Dart插件
  • Dart:是核心插件

编写一个测试文件:test.dart

代码语言:javascript
复制
void main(){
  // dart类似java,需要一个入口main函数
  print('123');
}

运行结果如上,说明Dart环境已经配置好了。

注意:

  • dart中的文件命名规范是使用下划线分隔符,例如test_hello,而不要使用驼峰命名了。可以去查看官方规范手册。

重要概念

  • 所有变量引用的都是 对象,每个对象都是一个 类 的实例。数字、函数以及 null 都是对象。所有的类都继承于 Object 类。
  • 尽管 Dart 是强类型语言,但是在声明变量时指定类型是可选的,因为 Dart 可以进行类型推断。在上述代码中,变量 number 的类型被推断为 int 类型。如果想显式地声明一个不确定的类型,可以使用特殊类型 dynamic。
  • Dart 支持泛型,比如 List(表示一组由 int 对象组成的列表)或 List(表示一组由任何类型对象组成的列表)。
  • Dart 支持顶级函数(例如 main 方法),同时还支持定义属于类或对象的函数(即 静态 和 实例方法)。你还可以在函数中定义函数(嵌套 或 局部函数)。
  • Dart 支持顶级 变量,以及定义属于类或对象的变量(静态和实例变量)。实例变量有时称之为域或属性。
  • Dart 没有类似于 Java 那样的 public、protected 和 private 成员访问限定符。如果一个标识符以下划线 (_) 开头则表示该标识符在库内是私有的。可以查阅 库和可见性 获取更多相关信息。
  • 标识符 可以以字母或者下划线 (_) 开头,其后可跟字符和数字的组合。
  • Dart 中 表达式 和 语句 是有区别的,表达式有值而语句没有。比如条件表达式 expression condition ? expr1 : expr2 中含有值 expr1 或 expr2。与 if-else 分支语句相比,if-else 分支语句则没有值。一个语句通常包含一个或多个表达式,但是一个表达式不能只包含一个语句。
  • Dart 工具可以显示 警告 和 错误 两种类型的问题。警告表明代码可能有问题但不会阻止其运行。错误分为编译时错误和运行时错误;编译时错误代码无法运行;运行时错误会在代码运行时导致异常。

变量

变量定义

代码语言:javascript
复制
//变量仅存储对象的引用
var name = 'Bob'; 

// 未初始化的变量拥有一个默认的初始化值:null。即便数字也是如此,因为在 Dart 中一切皆为对象,数字也不例外。
int lineCount;
assert(lineCount == null);

final和const

代码语言:javascript
复制
final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';

// const 关键字不仅仅可以用来定义常量,还可以用来创建 常量值
var foo = const [];
final bar = const [];
const baz = []; // 相当于 `const []` (Equivalent to `const []`)

// 还可以在变量中使用类型检查

// Valid compile-time constants as of Dart 2.5.
const Object i = 3; // Where i is a const Object with an int value...
const list = [i as int]; // Use a typecast.
const map = {if (i is int) i: "int"}; // Use is and collection if.
const set = {if (list is List<int>) ...list}; // ...and a spread

内置类型

Numbers

Dart 两种数据类型:intdouble

下面是字符串和数字之间转换的方式:

代码语言:javascript
复制
// 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');

Strings

使用单引号或双引号定义

代码语言:javascript
复制
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.";

字符串拼接可以使用+或者直接挨在一起的方式

代码语言:javascript
复制
var s1 = 'String '
    'concatenation'
    " works even over line breaks.";

var s2 = 'The + operator ' + 'works, as well.';

可以使用三个单引号或者三个双引号创建多行字符串:

代码语言:javascript
复制
var s1 = '''
你可以像这样创建多行字符串。
''';

var s2 = """这也是一个多行字符串。""";

只要是编译时常量都可以作为字符串字面量的插值表达式

代码语言:javascript
复制
void main(List<String> args) {

// These work in a const string.
const aConstNum = 0;
const aConstBool = true;
const aConstString = 'a constant string';

// These do NOT work in a const string.
var aNum = 0;
var aBool = true;
var aString = 'a string';
const aConstList = [1, 2, 3];

const validConstString = '$aConstNum $aConstBool $aConstString';
print(validConstString);

// 非编译时变量,不可以赋值
// const invalidConstString = '$aNum $aBool $aString $aConstList';

var invalidConstString = '$aNum $aBool $aString $aConstList'; // 编译时变量,可以赋值

}

string常用属性:

  • length
  • isEmpty
  • isNotEmpty
代码语言:javascript
复制
void main(List<String> args) {
  String a = '123'; 
  print(a.length); // 3

  print(a.isEmpty); // false

  print(a.isNotEmpty);  // true
}

string常用属性

  • contains
  • subString
  • startsWith
  • endsWith
  • indexOf
  • lastIndexOf
  • toLowerCase
  • toUpperCase
  • trim
  • trimLeft
  • trimRight
  • split
  • replaceXXX

Booleans

布尔类型只有truefalse

代码语言:javascript
复制
void main(List<String> args) {
  var test;

  // dart中一切皆是对象,所以要显示判断是否为null
  if(test == null){
    print('test is null');
  }
}

List

Dart中数组用List对象表示。

代码语言:javascript
复制
void main(List<String> args) {
  // 1.可以混合的list
  var list1 = [1, 2, 3, '4'];
  print(list1);

  // 2.只可以是指定类型的list
  List<int> list2 = [1, 2, 3];
  print(list2);

  // 3.用const关键字定义一个编译时数组常量
  List<int> list3 = const [1, 2, 3];
  print(list3);

  list3[1] = 4; // 编译时出错,不可以修改

  // 4.通过构造方式创建数组

  List fixedLengthList = new List(3);
  print(fixedLengthList.length); // 3

}

Dart中数组长度类似JavaScript语法。

代码语言:javascript
复制
void main(List<String> args) {
  var list = [1, 2, 3, 4];

  print(list.length); // true

  print(list[1] == 2);  // true

  list[2] = 4;
  print(list);  // [1, 2, 4, 4]
}

Dart中新增扩展操作符

代码语言:javascript
复制
void main(List<String> args) {
  var list1 = [1, 2, 3, 4, 5];
  var nullList;
  // 使用 ... 扩展list插入到另一个list
  var list2 = [0, ...list1];

  print(list2); // [0, 1, 2, 3, 4, 5]

  // 使用 ...? 如果nullList为空,则不插入
  var list3 = [0, ...?nullList];

  print(list3);
}

Dart 还可以使用Collection IfCollection for来根据条件创建数组。

代码语言:javascript
复制
void main(List<String> args) {

  /// 可以根据test条件,动态创建数组
  var test = true;

  var list = [
    1, 
    2,
    3,
    if(test) 4
  ];

  print(list);    // [1, 2, 3, 4]

  /// 也可以用循环遍历另一个数组创建一个数组
  var arrays = [1,2,3,4];

  var location = [
    '#0',
    for(var i in arrays) '#$i'
  ];

  print(location);    // [#0, #1, #2, #3, #4]
}

List常用的操作

代码语言:javascript
复制
void main(List<String> args) {
  var a = [1, 2, 3];
  a.add(4);
  print(a); // [1, 2, 3, 4]

  a.insert(1, 100);
  print(a);   // [1, 100, 2, 3, 4]

  a.remove(4);
  print(a);   // [1, 100, 2, 3]

  // 打乱顺序
  a.shuffle();
  print(a); // [2, 3, 100, 1]

  print(a.asMap()); // {0: 1, 1: 100, 2: 2, 3: 3}

  // 排序
  List<String> numbers = ['two', 'three', 'four'];
  // Sort from shortest to longest.
  numbers.sort((a, b) => a.length.compareTo(b.length));
  print(numbers);  // [two, four, three]

  // 截取
  a.sublist(1);
  print(a);

  // 可以调用print直接打印,或者自定义其他函数
  numbers.forEach(print);
}

Sets

创建sets

代码语言:javascript
复制
void main(List<String> args) {
  var names = <String>{}; // 类型+{}的形式创建Set。
  Set<String> names2 = {}; // 声明类型变量的形式创建 Set (This works, too).
  var names3 = {}; // 这样的形式将创建一个 Map 而不是 Set (Creates a map, not a

  print(names.runtimeType); // _CompactLinkedHashSet<String>
  print(names3.runtimeType); // _InternalLinkedHashMap<dynamic, dynamic>
}

注意: 如果忘记在 {} 上注释类型或赋值到一个未声明类型的变量上,那么 Dart 会创建一个类型为 Map<dynamic, dynamic> 的对象。

Maps

创建Map

代码语言:javascript
复制
void main(List<String> args) {

  // 相当于 Map<String, String> test = {}
  var test = {
    'a': '1',
    'b': '2',
    'c': '3'
  };

  // 可以不使用关键字New实例化一个对象
  var gifts = Map();
  gifts['first'] = 'partridge';
  gifts['second'] = 'turtledoves';
  gifts['fifth'] = 'golden rings';

}

操作Map

代码语言:javascript
复制
void main(List<String> args) {
  var map = {'a': 1, 'b': 2, 'c': 3};

  print(map.length); // 3

  print(map.isNotEmpty); // true

  print(map.isEmpty); // false

  print(map.keys); // (a, b, c)

  print(map.values); // (1, 2, 3)

  print(map.containsKey('c')); // true

  print(map.containsValue(4)); // false

  // 移除
  map.remove('a'); // {b: 2, c: 3}
  print(map);

  map.forEach((key, value) {
    print('key = $key, value = $value');
    // key = b, value = 2
    // key = c, value = 3
  });
}

运算符

算术运算符

以前我没用过取整运算符,这里记一下。

代码语言:javascript
复制
void main(List<String> args) {
  print(2 + 3 == 5);
  print(2 - 3 == -1);
  print(2 * 3 == 6);
  // 除
  print(5 / 2 == 2.5); // 结果是一个浮点数
  // 取整
  print(5 ~/ 2 == 2); // 结果是一个整数
  // 取余
  print(5 % 2 == 1); // 取余

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

自增与自减

文档中的自增与自减解释很棒。

  • ++var和--var,先对var变量进行计算,然后再赋值给另一个变量
  • var++和var--,先将var变量赋值给另外一个变量,然后再对自身进行操作
代码语言:javascript
复制
void main(List<String> args) {
  var a, b;

  a = 0;
  b = ++a; // 在 b 赋值前将 a 增加 1。
  print(a == b); // 1 == 1  

  a = 0;
  b = a++; // 在 b 赋值后将 a 增加 1。
  print(a != b); // 1 != 0, a = 1

  a = 0;
  b = --a; // 在 b 赋值前将 a 减少 1。
  print(a == b); // -1 == -1, a = -1

  a = 0;
  b = a--; // 在 b 赋值后将 a 减少 1。
  print(a != b); // -1 != 0
}

关系运算符

代码语言:javascript
复制
void main(List<String> args) {


  print(2 == 2);
  print(2 != 3);
  print(3 > 2);
  print(2 < 3);
  print(3 >= 3);
  print(2 <= 3);
}

类型判断运算符

当且仅当 obj 实现了 T的接口,obj is T 才是 true。

代码语言:javascript
复制
void main(List<String> args) {
  Emp emp = Emp();
  Person p = Person('张三');

  print(emp is Person);   // true

}
class Person{
  final _name;

  Person(this._name);
}
class Emp implements Person{
  // 必须实现
  get _name => '';
}

赋值运算符

  • 使用 = 来赋值
  • ??= 来为值为 null 的变量赋值
代码语言:javascript
复制
void main(List<String> args) {
  var a;
  var b;

  a = 1;
  //  当且仅当 b 为 null 时才赋值
  b ??= 2;

  print(a); // 1
  print(b); // 2


  var c = 9;
  c ~/= 2;

  print(c); // 4

}

逻辑运算符

使用逻辑运算符你可以反转或组合布尔表达式

代码语言:javascript
复制
void main(List<String> args) {
  var flag = true;
  const tab = 0;

  if (flag && (tab == 3 || tab == 0)) {
    print('hello'); // hello
  }
}

条件表达式

  • 如果赋值是根据布尔表达式则考虑使用 ?:
  • 如果赋值是根据判定是否为 null 则考虑使用 ??
代码语言:javascript
复制
void main(List<String> args) {
  // 三目运算符写法 good
  String playName(String name) => name != null ? name : 'Tom';

  // ??写法  best
  String playName3(String name) => name ?? 'Tom';

  // if - else 写法  bad
  String playName2(String name) {
    if (name != null) {
      return name;
    } else {
      return 'Tom';
    }
  }
}

级联运算符

级联运算符(..)可以让你在同一个对象上连续调用多个对象的变量或方法。

代码语言:javascript
复制
void main(List<String> args) {
  // 级联运算符严格意义上说并不是一个操作符,而是dart的特殊语法
  var p = Person()
  ..name = 'tom'
  ..age = 1
  ..say(); // name = tom, age = 1
  // 最后直接调用了say方法
}

class Person{
  String name;
  int age;

  void say(){
    print('name = $name, age = $age');  
  }
}

流程控制语句

与 JavaScript 不同的是,Dart 的 if 语句中的条件必须是一个布尔值,不能是其它类型

if和else

代码语言:javascript
复制
void main(List<String> args) {
  var bar = false;
  if (bar ==false){
    print('false');
  }else if( bar == true){
    print('true');
  }else{
    print('not true or false');
  }
}

for 循环

Dart在循环中的闭包会自动捕获。下面的例子在JavaScript中就会输出两个2。

代码语言:javascript
复制
void main(List<String> args) {

  // for 循环中的闭包会自动捕获循环的 索引值 以避免 JavaScript 中一些常见的陷阱
  var list = [];
  for(var i =0; i<2; i++){
    list.add(()=>print(i));
  }
  list.forEach((v) => v());
}

不需要数组索引时,使用forEach即可

代码语言:javascript
复制
  var prints = [1, 2,3];
  prints.forEach((v)=>print(v));

List和Set支持for-in

代码语言:javascript
复制
  // List和Set支持for-in
  var collections = [1, 2, 3, 4];
  for (var i in collections) {
    print('i = $i');
    print(i);
  }

while和do-while

  • while 循环会在执行循环体前先判断条件
  • do-while 循环则会先执行一遍循环体 再 判断条件:
代码语言:javascript
复制
void main(List<String> args) {
  var i = 0;
  while (true) {
    ++i;
    print(i); // 1 2 3
    if (i == 3) break;
  }
  print('i = $i');
  do {
    i++;
    print(i); // 4 5 6
    if(i == 6)break;
  } while (true);
}

break 和 continue

  • break 跳出循环
  • continue 继续循环
代码语言:javascript
复制
void main(List<String> args) {
  for(var i = 0; i<3; i++){
    print(i); // 输出0 1
    if(i ==1  ){ // 跳出循环
      break;
    }
    print('hi 我被执行了'); // 只输出一次
  }

  for(var i = 0; i<3; i++){
    print(i);// 输出 0 1 2
    if(i ==1  ){ // 继续循环
      continue;
    }
    print('hi 我被执行了'); // 输出2次,第二次被跳过了,循环继续
  }



}

switch 和 case

  • Switch 语句在 Dart 中使用 == 来比较整数、字符串或编译时常量,比较的两个对象必须是同一个类型且不能是子类并且没有重写 == 操作符
  • 每一个非空的 case 子句都必须有一个 break 语句
  • 当没有 case 语句匹配时,可以使用 default 子句来匹配这种情况
  • case如果为空,则采用fall-through形式
  • case如果为非空,则采用continue和label标签
  • case中的变量为局部变量
代码语言:javascript
复制
void main(List<String> args) {
  var name = 'annie';
  switch (name) {
    case 'tim':
      print('tim');
      break;
    case 'peter':
      print('peter');
      break;
    case 'jack': // fall-through 形式
    case 'tom':
      print('jack and tom');
      break;
    case 'annie':
      print('annie');
      continue ruth; // 继续执行标签为ruth的语句

    ruth:
    case 'ruth':
      print('ruth');
      break;
    case 'wilson':
      var test = 'test'; // 局部变量
      print(test);
      break;
  }

}

断言

  • 在开发环境下,添加断言来打断代码的执行
  • assert 是否生效依赖开发工具和使用的框架,在命令行中可以执行dart命令
代码语言:javascript
复制
void main(List<String> args) {
  var num = 100;
  // 命令行中执行 dart --enable-asserts 断言.dart 
  // 然后就会报错,后面的所有内容不再执行
  assert(num < 10);

  // 第二个参数可以指定异常错误信息
  assert(num < 90,
    '异常: ($num) 不小于90');

    // 如果直接执行 dart 断言.dart 因为是在生产环境,所以不会出现错误
}

函数

函数定义

代码语言:javascript
复制
void main(List<String> args) {

  // 函数最好定义返回值
  bool isBool(bool flag){
    var test = false;
    return test;
  }

  // 不写返回值倒是也行
  isBool2(bool flag){
    var test = false;
    return test;
  }

  // 使用箭头函数
  isBool3(bool flag) => flag = false;
}

命名可选参数

虽然参数是可选,但是也可以指定某个参数为必传,使用@required

代码语言:javascript
复制
import 'package:meta/meta.dart';

void main(List<String> args) {
  // 定义一个可选命名参数
  void saySomething({String name, int age}){
    print('name = $name, age = $age');
  }

  // 调用可选命名参数时,不需要写{}
  saySomething(name: 'tom', age: 12); // name = tom, age = 12
  saySomething(name: 'cook'); // name = cook, age = null

  // time参数必须传递
  // 使用@required 注解必须导入meta包
  // 导入meta.dart包,则必须在pubspec.yaml 文件中进行声明
  void playGame({String name,@required int time}){
    print('name = $name, age = $time');
  }

  // 虽然使用了@required 注解,并不会对应用程序报错,而是发出警告
  playGame(name: '和平精英');
}

位置可选参数

位置可选参数用 []表示

代码语言:javascript
复制
void main(List<String> args) {

  void say(String name, int age, [String address]){
    if(address == null){
      print('name = $name, age = $age');
    }else{
      print('name = $name, age = $age, address = $address');
    }    
  }
  say('tom', 123);  // name = tom, age = 123
  say('tim', 34, '北京');   // name = tim, age = 34, address = 北京


}

默认值

可以使用=给可选参数设置默认值

代码语言:javascript
复制
void main(List<String> args) {
  void startEng({bool oil = true, bool state = false}){
    return print(oil && state);
  }

  startEng(); // 默认false
  startEng(state:true); // true
  startEng(oil:true,state:true); // true

  // 如果name使用默认值,但是传递 age 呢?
  String say(String start, String end, [String name = 'jack', int age]){
    if(name != null){ // 永远不为null
      print('start = $start, end = $end, name = $name');
    }
    if(age!=null){
     print('start = $start, end = $end, name = $name, age = $age');
    }
  }

  say('北京','上海', '张三');
  say('河南','河北', 'jack', 22);
}

main函数

  • 所有Dart程序都必须有一个入口main函数
  • 可以在命令行中传递参数
代码语言:javascript
复制
void main(List<String> args) {
  print(args);

  // 命令行中没有传递参数时
  if(args.length == 0)return;

  // 命令行中执行  dart main函数.dart 1 test
  if(int.parse(args[0]) == 1){
    print('第一个参数为 ${args[0]}');
  }

  if(args.length == 2){
    print('参数的个数是 ${args.length}');
  }
}

函数作为一级对象

  • 将函数作为参数传递给另一个函数
  • 将函数作为一个变量
代码语言:javascript
复制
void main(List<String> args) {
  void say(int num){
    print('hello dart, and num is $num');
  }

  List<int> list = const [1,2,3,4];

  // 将函数作为参数传递给另一个函数
  list.forEach(say);

  // 将函数作为一个变量
  var printName = (v)=>print('you are print $v');
  printName('jack');  // you are print jack

  var printName2 = (v){ return print('another print name function $v');};
  printName2('tom');  // another print name function tom
}

匿名函数

  • 匿名函数就是没有函数名称的函数
  • 函数体只有单行时,可以使用箭头函数
代码语言:javascript
复制
void main(List<String> args) {
  var list = [1, 2, 3, 4];

  // 匿名函数
  list.forEach((v) {
    print(v);
  });
  // 箭头函数
  list.forEach((v) => print(v));

  List<String> getTime(List list, String times(str)) {
    List<String> tmp = [];
    list.forEach((v) {
      tmp.add(times(v));
    });
    return tmp;
  }

  String times(str) {
    return str * 3;
  }

  var list2 = ['h', 'e', 'l', 'l', 'o'];
  // 这里调用 times 时不需要写(),否则就变成了执行函数了
  print(getTime(list2, times)); // [hhh, eee, lll, lll, ooo]
}

词法作用域

代码语言:javascript
复制
bool topLevel = true;

void main() {
  var insideMain = true;

  void myFunction() {
    var insideFunction = true;

    // 内部函数可以逐级向上访问外部函数变量
    void nestedFunction() {
      var insideNestedFunction = true;

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

}

闭包

  • 函数对象的调用在它原始作用域之外,能够访问在它词法作用域内的变量
  • 函数可以封闭定义到它作用域内的变量
代码语言:javascript
复制
void main(List<String> args) {
  // 闭包就是一个函数对象
  // 函数可以封闭它作用域内的变量,即使是函数在外部调用
  Function sum(int add){ // 注意返回值类型是函数
    return (i) => add + i;
  }

  // 这个1就是add,然后被封闭了起来
  var sumAll = sum(1); 

  print(sumAll(1)); // 2


  // 闭包就是在一个函数中返回另一个函数
  a(){

    var count = 0;
    void printCount(){
        print(count ++);
    }
    return printCount;
  }

  var fun = a();

  // 想访问方法中的局部变量时,就使用闭包
  fun(); // 0
  fun(); // 1
}

函数相等性测试

  • 不同实例的函数之间不相等
  • 静态方法、顶级函数,都相等
代码语言:javascript
复制
void foo() {} // 定义顶层函数 (A top-level function)

class A {
  static void bar() {} // 定义静态方法
  void baz() {} // 定义实例方法
}

void main() {
  var x;

  // 比较顶层函数是否相等。
  x = foo;
  assert(foo == x);

  // 比较静态方法是否相等。
  x = A.bar;
  assert(A.bar == x);

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

  // 这两个闭包引用了相同的实例对象,因此它们相等。
  assert(y.baz == x);

  // 这两个闭包引用了不同的实例对象,因此它们不相等。
  assert(v.baz != w.baz);
}

返回值

  • 所有函数都有返回值
  • 如果没有指定就返回null
代码语言:javascript
复制
void main(List<String> args) {
  // 这里没有指定函数返回值
  // 实际上,如果指定了,编辑器就会报错
  foo(){}

  var test = foo();

  print(test); // null
}

(未完)


参考资料:

  • Dart语法学习 「https://www.jianshu.com/p/9e5f4c81cc7d」
  • 官方文档中文版「https://dart.cn/guides/language/language-tour」
  • 官网文档英文版「https://dart.dev/guides/language/language-tour」
  • Dart SDK API 中文版「http://www.shutongye.com/dartapi/index.html」
  • Flutter开发第一步-Dart编程语言入门「https://www.imooc.com/learn/1035」
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-03-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 前端修炼之路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 环境搭建
    • 1. 安装Dart SDK
      • 2. 配置编辑器的Dart插件
      • 重要概念
      • 变量
      • 内置类型
        • Numbers
          • Strings
            • Booleans
              • List
                • Sets
                  • Maps
                  • 运算符
                    • 算术运算符
                      • 关系运算符
                        • 类型判断运算符
                          • 赋值运算符
                            • 逻辑运算符
                              • 条件表达式
                                • 级联运算符
                                • 流程控制语句
                                  • if和else
                                    • for 循环
                                      • while和do-while
                                        • break 和 continue
                                          • switch 和 case
                                            • 断言
                                            • 函数
                                              • 函数定义
                                                • 命名可选参数
                                                  • 位置可选参数
                                                    • 默认值
                                                      • main函数
                                                        • 函数作为一级对象
                                                          • 匿名函数
                                                            • 词法作用域
                                                              • 闭包
                                                                • 函数相等性测试
                                                                  • 返回值
                                                                  领券
                                                                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档