Dart 是面向对象的编程语言,语法风格对于许多现有的开发人员来说都很熟悉,但对于前端来说,面向对象反而是不熟悉的,因为JavaScript的class在es6才出现,浏览器的兼容差导致前端开发在开始熟悉js的时候往往会避开class这类知识。随着前端webpack等打包程序、三大前端框架的出现,越来越多的前端er开始使用es6的知识来编写代码????扯远了扯远了。Dart的很多语法与ts可以说是十分相似(编程语言大差不差?),这对前端er学习dart提供了极大的便利,下面的内容部分会将Dart与js进行比较。
学习dart的目的是学习flutter,小目标,年前写一个小型flutter项目。
- 任何保存在变量中的都是一个 对象 , 并且所有的对象都是对应一个 类 的实例。 无论是数字,函数和 null 都是对象。所有对象继承自 Object 类。
- 尽管 Dart 是强类型的,但是 Dart 可以推断类型,所以类型注释是可选的。 在上面的代码中, number 被推断为 int 类型。 如果要明确说明不需要任何类型, 需要使用特殊类型 dynamic 。
- Dart 支持泛型,如 List
(整数列表)或 List (任何类型的对象列表)。 - Dart 支持顶级函数(例如 main() ), 同样函数绑定在类或对象上(分别是 静态函数 和 实例函数 )。 以及支持函数内创建函数 ( 嵌套 或 局部函数 ) 。
- 类似地, Dart 支持顶级 变量 , 同样变量绑定在类或对象上(静态变量和实例变量)。 实例变量有时称为字段或属性。
- 与 Java 不同,Dart 没有关键字 “public” , “protected” 和 “private” 。 如果标识符以下划线(_)开头,则它相对于库是私有的。 有关更多信息,参考 库和可见性。
- 标识符 以字母或下划线(_)开头,后跟任意字母和数字组合。
- Dart 语法中包含 表达式( expressions )(有运行时值)和 语句( statements )(没有运行时值)。 例如,条件表达式 condition ? expr1 : expr2 的值可能是 expr1 或 expr2 。 将其与 if-else 语句 相比较,if-else 语句没有值。 一条语句通常包含一个或多个表达式,相反表达式不能直接包含语句。
- Dart 工具提示两种类型问题:警告_和_错误。 警告只是表明代码可能无法正常工作,但不会阻止程序的执行。 错误可能是编译时错误或者运行时错误。 编译时错误会阻止代码的执行; 运行时错误会导致代码在执行过程中引发 [异常](#exception)。
显式类型声明String name = 'Bob';,直接将变量类型写出来。
动态类型声明var name = 'Bob';,根据变量的赋值推断变量类型。
未初始化的变量默认值为null。
final 和 const自我感觉区别在于,const定义的变量,在等于号的右边必须是个值,而不能是一个函数返回值,而final定义的变量,在等于号的右边可以是任意值。
相同点变量是值在初始化后不能改变。
变量类型
dynamic any = 'Bob';int int1 = 1;double double1 = 1.3;var one = int.parse('1');,double.parse('1.1');String oneAsString = 1.toString();,String piAsString = 3.14159.toStringAsFixed(2);String str = 'str'; String str0 = '123'+'456'+'789'
String str1 = '123'
String str2 = '789 ${str1} 456'
String str3 = '123''456''789'
String str4 = '''123
456
789'''
bool bool1 = true;// 检查 0 值。 var hitPoints = 0; assert(hitPoints <= 0);
// 检查 null 值。 var unicorn; assert(unicorn == null);
// 检查 NaN 。 var iMeantToDoThis = 0 / 0; assert(iMeantToDoThis.isNaN);
* 列表类型
`List<dynamic> list1 = [0,'1','2.0'];`,类似`JavaScript`的`Array`。
* Set类型
`Set<String> set1 = {'1','2','3'};`
`var set2 = <String>{};`
Set类型保证内部元素唯一,且内部元素无序。
Set类型对象添加元素
```dart
var elements = <String>{};
elements.add('fluorine');
elements.addAll(halogens);
* Map类型 `Map<String,String> map1 = {'1':'1','2':'2','3':'3'};` `var map2 = <String,String>{'1':'1','2':'2','3':'3'};` Map 是用来关联 keys 和 values 的对象。 keys 和 values 可以是任何类型的对象。 与`JavaScript`map对象类似。
* Rune Rune 用来表示字符串中的 UTF-32 编码字符。
* 函数 ```dart bool isNoble(int atomicNumber) { return _nobleGases[atomicNumber] != null; } ``` 数中只有一句表达式,可以使用简写语法: ```dart bool isNoble(int atomicNumber) => _nobleGases[atomicNumber] != null; ``` 可选参数:类似`JavaScript`,向函数传对象,在函数表达式上用解构赋值,没传就是null 位置可选参数:将参数放到 [] 中来标记参数是可选的: ```dart String say(String from, String msg, [String device]) {
... } ``` 默认参数值: 定义方法的时候,可以使用 = 来定义可选参数的默认值。 默认值只能是编译时常量。 如果没有提供默认值,则默认值为 null。 ```dart /// 设置 [bold] 和 [hidden] 标志 ... void enableFlags({bool bold = false, bool hidden = false}) {...} ```
JavaScript是在最外层环境执行开始函数,而dart把这些开始函数放在main中运行。JavaScript不同,for循环里自成闭包,而es5是会出现bug的。??
var a = b ?? 1;
理解:如果b不是null就返回b,是就返回1
?.
foo?.bar;
理解:从表达式foo中选择属性bar,除非foo为null
..
querySelector('#sample_text_id')
..text = 'Click me!'
..onClick.listen(reverseText);
理解:级联运算符 (..) 可以实现对同一个对像进行一系列的操作。
as,is,is!
import 'dart:html;' as html
理解:Typecast (也被用于指定库前缀),类ts的as。
if and else:普通判断
for loops:for循环
while and do-while loops:while/do-while循环
break and continue:跳出全部循环/本次循环
switch and case:选择case
assert:如果 assert 语句中的布尔条件为 false , 那么正常的程序执行流程会被中断。
throw FormatException('Expected at least 1 section');
throw 'Out of llamas!';
抛出异常
try {
} on OutOfLlamasException {
// 一个特殊的异常
} on Exception catch (e) {
// 其他任何异常
} catch (e) {
// 没有指定的类型,处理所有异常
rethrow;
} finally {
// 无论怎么样都会运行
}
on 来指定异常类型, 使用 catch 来 捕获异常对象。 如果仅需要部分处理异常, 那么可以使用关键字 rethrow 将异常重新抛出。
print('The type of a is ${a.runtimeType}');
import 'dart:math';
class Point {
num x, y;
Point(this.x, this.y);
num distanceTo(Point other) {
var dx = x - other.x;
var dy = y - other.y;
return sqrt(dx * dx + dy * dy);
}
}
Getter 和 Setter
Getter 和 Setter 是用于对象属性读和写的特殊方法。 回想之前的例子,每个实例变量都有一个隐式 Getter ,通常情况下还会有一个 Setter 。 使用 get 和 set 关键字实现 Getter 和 Setter ,能够为实例创建额外的属性。
class Rectangle {
num left, top, width, height;
Rectangle(this.left, this.top, this.width, this.height);
// 定义两个计算属性: right 和 bottom。
num get right => left + width;
set right(num value) => left = value - width;
num get bottom => top + height;
set bottom(num value) => top = value - height;
}
类似 (++) 之类操作符不管是否定义了 getter 方法,都能够正确的执行。 为了避免一些问题,操作符只调用一次 getter 方法, 然后把值保存到一个临时的变量中。
class A {
// 如果不重写 noSuchMethod,访问
// 不存在的实例变量时会导致 NoSuchMethodError 错误。
@override
void noSuchMethod(Invocation invocation) {
print('You tried to use a non-existent member: ' +
'${invocation.memberName}');
}
}
除非符合下面的任意一项条件, 否则没有实现的方法不能够被调用: receiver 具有 dynamic 的静态类型 。 receiver 具有静态类型,用于定义为实现的方法 (可以是抽象的), 并且 receiver 的动态类型具有 noSuchMethod() 的实现, 该实现与 Object 类中的实现不同。
var p = Point(2, 2);
// 为实例的变量 y 设置值。
p.y = 3;
// 获取变量 y 的值。
assert(p.y == 3);
// 调用 p 的 distanceTo() 方法。
num distance = p.distanceTo(Point(4, 4));
var p1 = Point(2, 2);
new关键字可选。
enum Color { red, green, blue }
枚举中的每个值都有一个 index getter 方法, 该方法返回值所在枚举类型定义中的位置(从 0 开始)。 例如,第一个枚举值的索引是 0 , 第二个枚举值的索引是 1。和Set不同,Set内部是没有索引的,无序的,每个元素唯一的。
class Musician extends Performer with Musical {
// ···
}
class Maestro extends Person
with Musical, Aggressive, Demented {
Maestro(String maestroName) {
name = maestroName;
canConduct = true;
}
}
通过创建一个继承自 Object 且没有构造函数的类,来 实现 一个 Mixin 。 如果 Mixin 不希望作为常规类被使用,使用关键字 mixin 替换 class 。
mixin Musical {
//...
}
抽象类是定义接口,而mixin是定义好变量,方法以及实现,然后大家都能用。
对于常见或广泛使用的工具和函数, 应该考虑使用顶级函数而不是静态方法。
abstract class Cache<T> {
T getByKey(String key);
void setByKey(String key, T value);
}
使用泛型函数
T first<T>(List<T> ts) {
// Do some initial work or error checking, then...
T tmp = ts[0];
// Do some additional checking or processing...
return tmp;
}
import 'dart:html';
import 参数只需要一个指向库的 URI。 对于内置库,URI 拥有自己特殊的dart: 方案。 对于其他的库,使用系统文件路径或者 package: 方案 。 package: 方案指定由包管理器(如 pub 工具)提供的库
import 'package:test/test.dart';
import 'package:lib1/lib1.dart';
import 'package:lib2/lib2.dart' as lib2;
// 使用 lib1 中的 Element。
Element element1 = Element();
// 使用 lib2 中的 Element。
lib2.Element element2 = lib2.Element();
// Import only foo.
import 'package:lib1/lib1.dart' show foo;
// Import all names EXCEPT foo.
import 'package:lib2/lib2.dart' hide foo;
import 'package:greetings/hello.dart' deferred as hello;
当需要使用的时候,使用库标识符调用 loadLibrary() 函数来加载库:
Future greet() async {
await hello.loadLibrary();
hello.printGreeting();
}
JavaScript///* *////文档注释以 /// 或者 /** 开始。 在连续行上使用 /// 与多行文档注释具有相同的效果。 HttpConnectionInfo
uiHandler
IOStream
HttpRequest
Id
DB
import 'dart:async';
import 'dart:html';
import 'package:bar/bar.dart';
import 'package:my_package/util.dart';
export 'src/error.dart';