一个|一个 JSer 的 Dart 学习日志(二)(变量、常量)
本文是“一个 JSer 的 Dart 学习日志”系列的第二篇,本系列文章主要以挖掘 JS 与 Dart 异同点的方式,在复习和巩固 JS 的同时平稳地过渡到 Dart 语言。1. 关键字 (表面上的)共同点
鉴于作者尚属 Dart 初学者,所以认识可能会比较肤浅和片面,如您慧眼识虫,希望不吝指正。
如无特殊说明,本文中 JS 包含了自 ES5 至 ES2021 的全部特性, Dart 版本则为 2.0 以上版本。
- 变量关键字
var
; - 常量关键字
const
。
1.1
var
变量的作用域
- JS 中
var
关键字声明的变量作用域是所在函数作用域,与此关联的还有一个很经典的例子(就是for
循环里setTimeout
那个,不赘述); - Dart 中
var
关键字声明的变量作用域是块级作用域。
> /* JS */| // Dart
> function foo(){| foo(){
>if(true){|if(true){
>var a = 321;
|var a = 321;
>}|}
>console.log(`a = ${a}`);
|print('a = $a');
>/* a = 321;
*/| // Getter not found: 'a'.
> }| }
1.2
const
的语义不同
- JS 中,
const
声明的常量可以是运行过程中临时计算得来的; - Dart 里,
const
声明的常量必须是编译时常量,即在运行前就必须确定它的值。
> /* JS */| // Dart
> var a = Date.now();
/* OK */| var a = new DateTime.now();
// OK
> const b = Date.now();
/* OK */| const b = new DateTime.now();
// NOT OK
2. 各自的特色
这里算是两种语言的特色语法大赏,因此不再列举它们的共同点。2.1
let
与 final
,各自的特色关键字- JS 中引入了
let
关键字来弥补var
的设计缺陷,但是 Dart 中的var
本身没有这些缺陷,大概是因此,Dart 没有let
关键字,舍不得let
的话,可以去隔壁学习 Rust; - Dart 中的
const
关键字声明的常量需要在编译时确定值,但是在日常编程的时候,我们有需求固定一些在运行中才能确定其值的变量,防止意外被修改,也可以给编译器提供一定的优化参考,这时候我们可以用final
,其特性可以参考 JS 中的const
。
- Dart 是一门强类型的语言,声明变量/常量的同时也可以显式地声明其类型,但变量类型与
var
关键字不能并列使用。
> var int a = 0; // 错误,`var` 与变量名不得并列使用 > vara = 0; // 正确,Dart 会推断类型 >int a = 0; // 正确,得到一个类型为 int 的变量 > > const int a = 0; // 正确,得到一个类型为 int 的编译时常量 > final int a = 0; // 正确,得到一个类型为 int 的常量 > > Set
a = {0}; // 正确, 所得 Set 可包含 int 和 double 子项
事实上,如果不显式声明变量类型,Dart 会根据所赋的值来推断变量的类型。2.3 Dart 用var a = 0
中,a
的类型将被推断为int
;var a = 0.1
中,a
的类型则为double
。
const
确定编译时常量
Dart 中的
const
声明的变量值在编译时就已经确定了,这应该是出于性能优化考虑,将一些运行时的计算量转移到编译过程,或避免在同一程序中重复执行的额外开销。
- 编译时就能确定变量值这么好的功能,如果只有
const
能享受的话,就太浪费了,所以声明变量的值为复杂数据类型的时候,可以用const
关键字标名这个值是一个编译时常量:
var a = const { 123456 }; Set
a = const { 123456 };
,但这个语法不适用于简单类型:
var a = const 123456; // 这将无法通过编译
。
var
- 在 JS 中,可以省略
var
,直接命名一个变量并赋值,这个变量会自动成为一个全局变量,此即 JS 的“隐式全局变量”,这是一个名声不佳的 JS 特性,开发中应避免使用;
本文 2.2 已经提到:Dart 的2.5 Dart 不存在变量提升var
关键字与类型声明不能并列使用,从某种意义上来讲,也算是省略了关键字var
。
- 变量提升也是 JS 中的一个槽点,所幸 ES6+ 的
let
和const
以“死区”的方式避免了这个槽点,证明 TC39 也不喜欢这个特性; - Dart 是一门“正常”的语言,遵循变量先声明后使用的原则,不存在变量提升。
> /* JS */| // Dart
> var b = a + 1;
| var b = a + 1;
> var a = 100;
| var a = 100;
> console.log(`b = ${b}`);
| print('b = $b');
> // b = NaN| // 无法通过编译
3. 总结
&
对比
【一个|一个 JSer 的 Dart 学习日志(二)(变量、常量)】参见下表:特性 | JS | Dart |
---|---|---|
var |
函数级变量关键字 | 块级变量关键字 |
const |
常量关键字 | 编译时常量关键字 |
let |
块级变量关键字 | |
final |
运行时常量关键字 | |
类型声明 | 支持类型声明,也可交由 Dart 自动推断类型 |
推荐阅读
- 热闹中的孤独
- JAVA(抽象类与接口的区别&重载与重写&内存泄漏)
- 放屁有这三个特征的,请注意啦!这说明你的身体毒素太多
- 一个人的旅行,三亚
- 布丽吉特,人生绝对的赢家
- 慢慢的美丽
- 尽力
- 一个小故事,我的思考。
- 家乡的那条小河
- 《真与假的困惑》???|《真与假的困惑》??? ——致良知是一种伟大的力量