一个 JSer 的 Dart 学习日志(五):基本数据类型

算法建
• 阅读 2582

致读者

本文是“一个 JSer 的 Dart 学习日志”系列的第五篇,本系列文章主要以挖掘 JS 与 Dart 异同点的方式,在复习和巩固 JS 的同时平稳地过渡到 Dart 语言。
如无特殊说明,本文中 JS 包含了自 ES5 至 ES2021 的全部特性, Dart 版本则为 2.0 以上版本。
鉴于作者尚属 Dart 初学者,所以认识可能会比较肤浅和片面,对知识的概括难免有所疏漏,如您慧眼识虫,望不吝指正。本系列文章首发于思否平台,勘误及新增内容也仅限于思否,如您是在别的地方看到本文,请移步思否以免看到未修订的内容。

关于

ES5 的五种基本类型(NumberStringNullUndefinedBoolean)是老生常谈的面试题,ES2015 带来的 Symbol 和 ES2019 新增的 BigInt 丰富了 JS 可用的基本类型。
在数据结构方面,JSer 们一开始只能基于内建的 ObjectArray 组织数据,其间常常伴着一些不成文的约束,直到 ES6 带来了 MapSet 。而在内建数据类型方面,Dart 的起点明显要比 JS 高。

JS 作为一门解释性的语言,其语言标准对运行的宿主有所约束(虽然厂商未必遵循此标准),所以在 JS 的标准中可以明确内存的使用方式,例如除了变量的引用之外,某些数据也存放在栈内存中,这些数据即所谓“基本类型”数据。
而 Dart 往往需要编译到其他语言,通过标准明确地约束宿主的行为只会徒增工作量,这也许就是 Dart 没有明确规定“基本类型”的原因。

但这并不妨碍我们用 Dart 中那些功能相仿的类型与 JS 的基本类型作比。

一、 Number

共同点

  • 使用十进制数字字面量声明;
  • 使用十六进制的字面量声明;
  • 使用科学计数法声明:

    /****** Both JS and Dart ******/
    var dec = 42;
    var hex = 0X2A;
    var sic = 4e2;

不同点

1. Dart 没有二进制字面量

  • JS 中使用 0b 开头的语法声明二进制字面量(b也可大写);
  • Dart 不支持二进制字面量:

    > /*  JS  */                           | // Dart
    > var bin = 0b101010;                  | // var bin = 0b101010;
    >                                      | // 去掉上面的注释,将无法通过编译

2. intdouble

  • JS 的Number类型均以双精度浮点类型存储和计算;
  • Dart 的Number分为整形int和双精度浮点类型double,以应对不同的表示和运算需求:

    > /*  JS  */                           | // Dart
    > var i = 1;                           | var i = 1;
    > var d = 1.1;                         | var d = 1.1;
    > console.log(typeof i);               | print(i.runtimeType);
    > console.log(typeof d);               | print(d.runtimeType);
    > // number                            | // int
    > // number                            | // double
    不过,使用 Dartpad 实测得知:
    如果小数点后只有 0的话,d.runtimeTypeint
    但如果将 d 声明为 numint ,并作为double类型的函数参数,将无法通过编译。
    是否说明 Dart 设计者其类型推断功能过于自信?
另外在 Dart 中:
如果两个数字相减为 0,那么使用==判断相等的时候,返回的是true
doubleint 相加,结果的类型为 double

3. 从其他类型创建数字

  • 在 JS 中使用 Number 构造函数可以创建数字(但不能使用new关键字),如果参数是一个其他类型的表达式的话,会将此表达式转为数字类型;
  • 在 Dart 中仅可使用 num.parse/num.tryParse将字符串转为数字,:

    var a = Number('2');                | var a = num.parse('2');
    parse 遇到无法转为数字的字符串会抛错;
    tryParse 遇到无法转为数字的字符串则返回null
    二者都会进行严格的参数类型匹配。

4. 特殊的数值

  • 对应 JS 中的 NaN,但是没有NaN字面量;
  • Dart 中的 double.maxFinite对应 JS 中的 Number.MAX_VALUE(但是具体值要看宿主环境);
  • Dart 中的 double.minPositive 对应 JS 中的 Number.MIN_VALUE
  • Dart 中的 double.infinity 对应于 JS 中的 Number.POSITIVE_INFINITY
  • Dart 中的 double.negativeInfinity 对应于 JS 中的 Number.NEGATIVE_INFINITY
不知道算共同点还是不同点。
Dart 中的 int 类型更像 JS 中的 BigInt,上面这几个值,它们——都!没!有!

二、Boolean VS 布尔类型

共同点

  • 使用字面量声明。

不同点

1. 没有隐式类型转换和万能的构造函数

  • JS 中可以在本该使用 Boolean 类型的地方使用值为任何类型的表达式,这些表达式的值在运算时会被转换为一个布尔值,此过程涉及一个非常复杂的真值表,其效果等同于调用Boolean(exp)
  • Dart 中使用bool类型的地方必须使用该类型,并且bool不是一个可执行的函数或构造函数,也没有转换其他类型值的方法。
因此在任何地方判断真假的时候一定要显式地将表达式转为布尔类型。

三、String VS Strings

共同点

  • 可使用单双引号(即"')声明字符串字面量;
  • 使用反斜杠(\)转义特殊字符;
  • 使用加号(+)拼接字符串:

    /******  Both JS and Dart ******/
    var stringA = 'This is a string';
    var stringB = 'This\'s a string';
    var stringC = stringA + stringB;

不同之处

1. 多行字符串

  • ES5 是没有多行字符串字面量的,使用 \n 表示换行符,ES6 新增了反引号(`)语法,可以直接回车输入换行;
  • Dart 使用三引号('''""")语法表示多行字符串:

    > /*  JS  */                           | // Dart
    > const a =                            | const a =
    >   `Line 1st                          |   '''Line 1st;
    > Line 2nd`;                           | Line 2nd''';
    > console.log(a);                      | print(a);
    > // Line 1st \nLine 2nd               | // Line 1st \nLine 2nd 

2. 字符串模板

  • ES5 同样没有字符串模板功能,开发者通常使用字符串拼接或片段替换来向字符串嵌入表达式,而 ES6 新增的反引号语法中可以使用${exp}向字符串中来达到同样的效果;
  • Dart 中所有字符串均可使用 ${exp}$varName将表达式/变量的值嵌入字符串中:

    > /*  JS  */                           | // Dart
    > const val = 'expression';            | const val = 'expression';
    > var oldVer = 'This is ' + val;       | const oldVer = "This is $val";
    > const newVer = `This is ${val}`;     | const newVer = 'This is ${val}';
    > console.log(oldVer === newVer);      | print(oldVer == newVer);
    > // true                              | // true

3. 没有隐式转换和构造函数

  • 在 JS 中,我们可以使用字符串连接任何表达式得到一个新的字符串,该表达式的.toString方法会被默认执行,另外也可以使用String(exp)将表达式转为字符串;
  • 在 Dart 中字符串不能与其他类型的表达式进行连接,Strings也不是可调用的函数或构造函数。
借助操作符重载功能,我们应该可以在 Dart 中实现隐式类型转换,唯一的问题就是:我们有这个必要吗?

4. raw字符串

  • JS 没有 raw字符串,也没有类似的概念;
  • Dart 中,在引号前加一个r,表示此字符串中的斜杠不是转义符:

    // Dart only
    const raw = r'In a raw string, not even \n gets special treatment.';

    这里的 \n 不会被视作换行符。

当然,作为 UI 编程中最为常见的基本类型,字符串有着很多便利的方法和丰富的用法,预计列举这些异同点会占用较大篇幅,此处按下不表。

四、Symbol

共同点

  • 使用 Symbol(String t)创建一个 Symbol

    /****** Both JS and Dart ******/
    const symbol = Symbol('symbol');

不同点

1. 不同 Symbol 实例的相等性

  • JS 中的不同 Symbol 是不相等的,即便创建时传入的字符串一致;
  • Dart 中向Symbol传入的字符串一致,则所得实例相等:

    > /*  JS  */                         | // Dart
    > const a = Symbol('symbol');        | const a = Symbol('symbol');
    > const b = Symbol('symbol');        | const b = Symbol('symbol');
    > console.log(a == b);               | console.log(a == b);
    > // false                           | // true

2. #号语法

  • 在 Dart 中可以使用 # 快捷地声明一个常量Symbol

    #symbol;
    print('This is ${#symbol}');
    // This is Symbol("symbol")

    注意

    • 使用的时候也要带上 # 号;
    • 声明的Symbol明确是编译时常量,因此不能再使用varconstlate等关键字,也不能使用 Symbol 声明其类型。

五、Null VS Null && Undefined

  • JS 中有两种空值:undefinednull,类型分别为undefinedNull,前者常作为未赋值变量的默认值,而后者往往作为一些接口无目标值时的返回值;
  • Dart 中只有 null 空值,作为未赋值变量的默认值,在空安全(sound null safety)模式下须使用 Type? 语法才能赋值:

    String? someString = null;
    // 空安全模式下,需要使用`?`,才能为变量声明初值
点赞
收藏
评论区
推荐文章
blmius blmius
4年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
5年前
Dart | 浅析dart中库的导入与拆分
前言最近十分热门的跨平台框架使用了一门比较生僻的编程语言dart。dart语言本身深受早期一些编程语言的影响。特别是Smalltalk,Java和JavaScript。我是从Java语言向dart过度的,一开始感觉很不错,快速就对这门语言有了一个初步的认识,并能够写小段代码了。但在flutter的不断学习过程中,我遇到了不少因为dart的一些语
待兔 待兔
5年前
flutter -- dart基础之dart简介和安装
Dart介绍:Dart是由谷歌开发的计算机编程语言,它可以被用于web、服务器、移动应用和物联网等领域的开发。Dart诞生于2011年,号称要取代JavaScript。但是过去的几年中一直不温不火。直到Flutter的出现现在被人们重新重视。要学Flutter的话我们必须首先得会Dart。da
待兔 待兔
5年前
[Dart]Dart语言之旅<一>:简介
我们假定你已经知道如何用另一种语言编程,《Dart语言之旅》将向你展示了如何使用每个主要的Dart特性——从变量和运算符到类和库。一个基本的Dart程序下面的代码使用了许多Dart最基本的功能://Defineafunction.printNumber(numaNumber){print('Thenumberis$a
浩浩 浩浩
4年前
【Flutter 实战】Dart语言简介
1.4Dart语言简介在之前我们已经介绍过Dart语言的相关特性,读者可以翻看一下,如果读者已经熟悉Dart语法,可以跳过本节,如果你还不了解Dart,也不用担心,按照笔者经验,如果你有过其他编程语言经验(尤其是Java和JavaScript)的话会非常容易上手Dart。当然,如果你是iOS开发者,也不用担心,Dart中也有一些与Swift比较相似的特
Stella981 Stella981
4年前
Flutter 介绍、运行环境
Flutter是谷歌公司开发的一款开源、免费的移动UI框架,可以让我们快速的在Android和iOS上构建高质量App。它最大的特点就是跨平台、以及高性能。Flutter基于谷歌的dart语言,如果没有任何Dart语言的基础,不建议直接学习Flutter。建议先学习Dart语言的基本语法。然后再进入Flutter的学习
Stella981 Stella981
4年前
OFBiz 快速入门——续二
OFBiz快速入门——续二2011年03月17日星期四00:03OFBiz 快速入门2.5 创建一个文件,取名为(controller.xml),被OFBiz webapp控制器使用的。在没有额外增加功能时,这个文件内容非常的小与简单,如下:<?xml version"1.0" encoding"UTF8"?<siteco
Wesley13 Wesley13
4年前
Java日期时间API系列36
  十二时辰,古代劳动人民把一昼夜划分成十二个时段,每一个时段叫一个时辰。二十四小时和十二时辰对照表:时辰时间24时制子时深夜11:00凌晨01:0023:0001:00丑时上午01:00上午03:0001:0003:00寅时上午03:00上午0
飞龙AI 飞龙AI
9个月前
DevEcoStudio 中使用模拟器时如何过滤日志
DevEcoStudio中使用模拟器时如何过滤日志鸿蒙核心技术鸿蒙开发者工具DevEcoStudio在HilogSettingsFilter设置Logmessage:A03d00/JSAPP当你看到不断更新的日志时,你会不会崩溃因为Nofilters模式下
算法建
算法建
Lv1
好坏都忍住,也算是进步。
文章
3
粉丝
0
获赞
0