当前位置: 首页 > Web前端 > JavaScript

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

时间:2023-03-27 10:29:06 JavaScript

亲爱的读者本文是“一个JSer的Dart学习日志”系列文章的第五篇。并在顺利过渡到Dart语言的同时固化JS。如无特殊说明,本文JS包含ES5到ES2021的所有特性,Dart版本为2.0及以上版本。由于笔者还是Dart初学者,理解可能比较肤浅和片面,难免会忽略知识的泛化。本系列文章首发于四佛平台,勘误及新增内容仅限于四佛。如果您在别处阅读此文,请移步四方,以免看到未修改的内容。ES5的五种基本类型(Number、String、Null、Undefined、Boolean)是常见的面试题。ES2015带来的Symbol和ES2019新增的BigInt丰富了JS可用的基本类型。在数据结构方面,JSers一开始只能基于内置的Object和Array来组织数据,往往伴随着一些不成文的约束,直到ES6带来了Map和Set。在内置数据类型方面,Dart的起点明显高于JS。JS是一种解释型语言,它的语言标准对运行主机有限制(虽然厂商可能不遵循这个标准),所以可以在JS标准中规定内存使用方式,比如除了变量引用,还有一个某些数据也存储在堆栈内存中,这就是所谓的“基本类型”数据。然而,Dart往往需要编译成其他语言,通过标准明确约束宿主的行为只会增加工作量。这可能就是Dart没有明确规定“基本类型”的原因。但这并不妨碍我们将Dart中那些功能相似的类型与JS的基本类型进行比较。1.Number的共同特点使用十进制字面量声明;使用十六进制文字声明;使用科学计数法声明:/******BothJSandDart******/vardec=42;varhex=0X2A;varsic=4e2;差异1.Dart没有二进制文字。在JS中,使用0b开头的语法来声明二进制字面量(b也可以大写);Dart不支持二进制文字:>/*JS*/|//飞镖>varbin=0b101010;|//varbin=0b101010;>|//如果去掉上面的注释,会编译失败2.int和doubleJS的Number类型都是按双精度浮点类型存储和计算的;Dart的Number分为整型int和双精度浮点-点类型double以满足不同的表示和操作要求:>/*JS*/|//飞镖>vari=1;|vari=1;>vard=1.1;|vard=1.1;>console.log(typeofi);|print(i.runtimeType);>console.log(typeofd);|print(d.runtimeType);>//数字|//整数>//数字|//double但是,使用Dartpad,发现如果小数点后只有0,d.runtimeType为int;但如果将d声明为num或int并作为double类型的函数参数,则无法通过编译。这是否意味着Dart设计者对其类型推断能力过于自信?另外,在Dart中:如果两个数相减为0,那么在使用==判断相等时,返回true;double和int相加,结果类型为double。3.从其他类型创建数字使用JS中的Number构造函数创建数字(但不能使用new关键字)。如果参数是其他类型的表达式,则将表达式转换为数字类型;在Dart中只有num.parse/num.tryParse可以用于将字符串转换为数字:vara=Number('2');|vara=num.parse('2');parse遇到无法转换为数字字符串的字符会抛出错误;tryParse遇到不能转为数字的字符串会返回null;两者都将执行严格的参数类型匹配。4、特殊值对应JS中的NaN,但没有NaN字面量;Dart中的double.maxFinite对应JS中的Number.MAX_VALUE(但具体值取决于宿主环境);Dart中的double.minPositive对应JS中的Number.MAX_VALUENumber.MIN_VALUE;Dart中的double.infinity对应JS中的Number.POSITIVE_INFINITY;Dart中的double.negativeInfinity对应JS中的Number.NEGATIVE_INFINITY。不知道是共性还是差异。Dart中的int类型更像是JS中的BigInt。以上数值,一应俱全!没有!有!2.BooleanVSBoolean类型有一个共同点就是字面量声明。区别1.没有隐式类型转换和通用构造函数。在JS中,应该使用布尔类型的地方可以使用任何类型的表达式。这些表达式的值在运算时会被转换为布尔值。这个过程涉及到一个非常复杂的真值表,相当于调用了Boolean(exp);Dart中使用bool类型的地方必须使用,bool不是可执行的函数或构造函数,也不是转换其他类型值的方法。因此,在任何地方判断真假时,都必须将表达式显式转换为布尔类型。3.StringVSStrings的共同特点可以使用单引号和双引号(即"or')声明字符串字面量;使用反斜杠(\)转义特殊字符;使用加号(+)连接字符串:/******JS和Dart都一样****/varstringA='Thisisastring';varstringB='This\'sastring';varstringC=stringA+stringB;区别1.多行字符StringES5做没有多行字符串字面量,用\n表示换行符,ES6增加了反引号(`)语法,可以直接回车换行;Dart使用三引号('''或""")多行字符串的语法:>/*JS*/|//飞镖>consta=|consta=>`第一行|'''第一行;>第二行`;|第2行''';>console.log(a);|print(a);>//第一行\n第二行|//Line1st\nLine2nd2.StringtemplateES5同样没有字符串模板功能,开发者通常使用字符串拼接或者片段替换的方式在字符串中嵌入表达式,而ES6新的反引号语法可以使用${exp}到字符串来实现同样的功能影响;Dart中的所有字符串都可以使用${exp}或$varName来对字符串中嵌入的表达式/变量的值进行赋值:>/*JS*/|//Dart>constval='表达式';|constval='expression';>varoldVer='Thisis'+val;|constoldVer="这个is$val";>constnewVer=`Thisis${val}`;|constnewVer='Thisis${val}';>console.log(oldVer===newVer);|print(oldVer==newVer);>//true|//true3.没有隐式转换和构造函数在JS中,我们可以使用字符串拼接任意表达式得到一个新的字符串,默认会执行表达式的.toString方法。另外,可以使用String(exp)将表达式转换成字符串;在Dart中,字符串不能与其他类型的表达式拼接,字符串也不是可调用的函数,也不是构造函数。借助运算符重载,我们应该可以在Dart中实现隐式类型转换,唯一的问题是:我们需要这个吗?4.RawstringJS没有rawstring,也没有类似的概念;在Dart中,在引号前加一个r表示这个字符串的slashinisnotescapecharacter://Dartonlyconstraw=r'Inarawstring,neednoteven\ngetsspecialtreatment.';这里的\n不会被视为a换行符。当然,作为UI编程最常见的基本类型string,有很多方便的方法和丰富的用法。预计罗列这些相同点和不同点会占用大量篇幅,这里就不一一列举了。4、Symbol的共同点使用Symbol(Stringt)创建一个Symbol:/******BothJSandDart****/constsymbol=Symbol('symbol');区别1.不同的Symbol实例相等不同的Symbol在JS中是不相等的,即使创建时传入的字符串是一致的;在Dart中,传入Symbol的字符串是一致的,结果实例是相等的:>/*JS*/|//Dart>consta=Symbol('symbol');|consta=Symbol('symbol');>constb=Symbol('symbol');|constb=Symbol('symbol');>console.log(a==b);|console.log(a==b);>//假|//true2.Dart中可以使用#语法快速声明一个常量Symbol:#symbol;print('Thisis${#symbol}');//ThisisSymbol("symbol")注意#应该使用时也要用到;声明的Symbol显然是编译期常量,所以不能再使用var、const、late等关键字,也不能使用Symbol来声明其类型。5.NullVSNull&&UndefinedJS空值有两种类型:undefined和null,类型分别是undefined和Null。前者常用作未赋值变量的默认值,后者常用作某些接口没有目标值时的返回值;Dart里面只有null值,作为未赋值变量的默认值,在健全的null安全模式下,Type?必须使用语法来赋值:String?someString=null;//在健全的null安全模式下,需要使用`?`,为变量声明一个初始值