挑战TJS Section1.4:变量的数据类型
正篇
Yuu:这次接着上次的话题,介绍变量可以存储的数据类型。
Yuni:什么是数据类型?像是数字、字母之类的?
Yuu:嗯嗯。TJS变量可以处理以下的数据类型。
/TJS支持的数据类型/
类型 | 介绍 |
---|---|
void | 表示什么都没有(变量内部是空) |
整数 | 整数,比如0、100、-256 |
实数 | 包括小数的数值。比如0.1、-123.456 |
字符串 | 一系列字符组成的整体,比如“abc”、“文本” |
对象 | 对象、方法、类、类型对象等等,由new创建 |
八位字符串 | 处理二进制数据的类型 |
Yuni:第一次看的话还挺多内容的。
Yuu:毕竟TJS变量可以处理很多类型。首先,来看void。
Yuni:void?
Yuu:void的意思是表达“什么都没有”。如果一个变量的值是void类型,它表示变量中没有任何东西。用盒子举例子的话,就是说盒子里面是空的。
Yuni:可以说它是0吗?
Yuu:不,它们并不同。0代表了箱子里有一个数字,不过它的值0.而void表示箱子里根本就没有。比如说,一个变量如果在声明后没有赋值的话,它就是void类型的,因为它内部不存在任何数据。
Yuni:嗯…我也不知道我有没有理解…
Yuu:嘛,现在你不必过于深入地理解。现在有一种void类型变量存储的是一种“空”状态的感觉就好。
Yuni:好的。
Yuu:下面是整数类型(整型)。这是种大家都很熟悉的类型。
Yuni:是呀。它指的是像0、1、2、3这样的数字对吧。哦,还有能有负数,像-1、-2、-3…
Yuu:没错。顺便说一下,TJS可以表示的数值范围非常大,从-922,337,236,854,775,808到922,337,236,854,775,807.译者注:整型范围是 -263~263-1.
Yuni:啊,这么大的么。
Yuu:嗯,这样你就可以完成大部分常见的运算了。
Yuni:是啊,这么大的数值范围岂不是什么计算都可以进行了。译者注:对于游戏来说还好,科学计算的话这是远远不够的。
Yuu:下一个是实数类型。它是个拓展整数表示范围的类型,因此小数也就可以表示了。
Yuni:我们可以使用包含小数点的数字,例如0.01, -1.234了吗?
Yuu:对的。并且实数可以表示特别大或特别接近0的数值,例如10000000000000000000000000000000000.0和0.000000000000000000000000000001。
Yuni:哇,我都不知道该怎么读第一个数字…
Yuu:嘛,通常我们都不会直接用这样的数字,也不会怎么出现。下一个是字符串类型。我想它应该好理解了,因为先前使用过好几次。
Yuni:嗯。它是当在消息框中显示语句时的字符数据。
Yuu:对。字符串的内容需要使用成对的双引号或单引号括起来。译者注:如果使用双引号,那起止都要是双引号;单引号也是这个道理。一单一双是不合法的。
var string1 = "abc";
var string2 = 'abc';
Yuu:在上面的脚本中,string1
和string2
的内容是相同的。
Yuni:为什么要有两种表示方法呢?
Yuu:它是用来解决字符串中包含双引号/单引号的情况,比如一个字符串使用双引号包含"字符串"。
。当你直接使用的时候…
/错误的表达/
var message = "使用双引号包含"字符串"。";
Yuu:在上面的例子中,“字符串”三个字因为message的自带的双引号跳了出来,所以会导致错误。但是…
/这种表达没问题/
var message = '使用双引号包含"字符串"。';
Yuu:这么写没问题,是因为整体字符串被认为是使用单引号括起来的,因此里面的双引号就不会被认为是字符串结束的标志。当然,单引号和双引号反过来也是可以的。
/这种表达也没问题/
var message = "使用单引号包含'字符串'。";
Yuu:也是没问题的。
Yuni:明白了。
Yuu:还有一种使用转义字符的方式来解决这个问题,但是它可能会造成困扰,因此我就跳过这个部分了。译者注:这部分会在下边的要点总结中讲解。 下一个是对象类型。对象类型有多种,因为它比较复杂,我这里只介绍一种。
Yuni:好。
Yuu:在使用Date类方法时,存储Date信息的“d先生”就是对象类型。
Yuni:嗯嗯,之前说过d也是一个变量。
Yuu:对。在TJS中,我们可以通过变量来操作复杂的数据,这样的变量就是对象类型。
Yuni:很深奥呢…
Yuu:嘛嘛,很快会掌握的。最后,有一种八进制类型可以处理二进制数据…它很少被使用并且在电子表的例子中不会涉及,所以这里先跳过。
Yuni:哦是吗?
Yuu:是的。如果你想了解这部分的详情,可以阅读TJS文档的“オクテット列に対する操作”部分。
Yuni:好的。
Yuu:现在我们介绍完了数据类型。下面我们要编写显示“何年何月何日几时几分几秒”的脚本了。
Yuni:哦,刚才说了这么多,这个目标我都快忘了…
Yuu:下面写一个使用变量来存储年月日时分秒的脚本。
Yuni:我来写!?
Yuu:好。如果你能理解讲解的全部内容,不妨把它当做一个练习试着自己完成。
Yuni:好的,来吧。我从上次写好的存储year的脚本这里开始…
var d = new Date();
var year; // 声明变量
year = d.getYear(); // 将年份的数值存入year中
Yuni:到现在为止有问题吗?
Yuu:没问题。哦,这里可以这样…
var d = new Date ();
var year = d.getYear (); // 将年份值作为初始值直接赋值给变量
Yuu:这么写year
会初始化为getYear()
的值,它和先声明再赋值的写法结果一样。
Yuni:哦,这么来声明d比较好,之后建议这么书写。
Yuu:嗯。
Yuni:下一个是月份了,使用变量month
…
var d = new Date();
var year = d.getYear(); // 将年份值作为初始值直接赋值给变量
var month = d.getMonth(); // 将月份值作为初始值直接赋值给变量
Yuni:欧了。
Yuu:这样不行。
Yuni:诶,为什么!?
Yuu:之前说过,getMonth()
得到的数值比真实月份小1…
Yuni:哦对了,我需要再加上1.
Yuu:正是这样。
Yuni:那么…
var d = new Date();
var year = d.getYear(); // 将年份值作为初始值直接赋值给变量
var month = d.getMonth()+1; // 将(月份值+1)作为初始值直接赋值给变量
Yuni:这样如何?
Yuu:嗯,没问题。
Yuni:剩下的部分像这样…
var d = new Date();
var year = d.getYear(); // 将年份值作为初始值直接赋值给变量year
var month = d.getMonth() + 1; //将(月份值+1)作为初始值直接赋值给变量month
var day = d.getDate(); // 将日期值作为初始值直接赋值给变量day
var hour = d.getHours(); // 将小时值作为初始值直接赋值给变量hour
var minute = d.getMinutes(); // 将分钟值作为初始值直接赋值给变量mounte
var second = d.getSeconds(); // 将秒钟值作为初始值直接赋值给变量second
Yuni: 这样如何?
Yuu:嗯,完美。
Yuni:yeah,我能很好地写出来了!
Yuu:好,下面来介绍使用按照“年月日时分秒”的格式显示变量中的值。
Yuni:这个怎样完成?
Yuu:使用“字符串的加法”。译者注:操作符是加号,因此叫做字符串的加法。本身,该操作称为字符串的连接更为妥当。
Yuni:额,能添加字符串的吗?
Yuu:嗯,我们使用加号添加字符。不过这个“加法”更像是“连接”,而不是加法。尝试运行以下脚本。
Yuni:好。
/字符串加法/
var mon = "一";
var day = "星期";
var monday = day + mon;
System.inform(monday);
Yuni:还真是。“星期”和“一”连接成了“星期一”,然后显示了出来。
Yuu:你可以使用这样的方法来创建“何年何月何日几时几分几秒”的字符串。例如“何年”就可以这么表示。
/显示年份/
var d = new Date();
var year = d.getYear(); // 将年份值作为初始值直接赋值给变量year
var message = year + "年"; // 年份值与“年”连接
System.inform(message);
Yuni:嗯,这样“2018年”就显示出来了。
Yuu:那么,还有一个疑问。
Yuni:嗯…?
Yuu:你觉得year
变量的什么类型?
Yuni:嗯…因为year
的值是getYear()
的返回值,年份是2018,所以说…是整型?
Yuu:没错。
Yuni:太好了,说对了。
Yuu:可是你想啊,如果year
是个整数,你对第3行的加法运算有什么想法吗?
Yuni:诶,这就是个普通的加法啊…啊!"年"
是个字符串,因此加法是对整数和字符串进行的!?
Yuu:就是这样。
Yuni:这的确奇怪啊…但是现实上并没有什么问题…这是这么搞的?
Yuu:实际上,如果字符串和数值同时出现在加法中,数值会自动转成字符串类型。译者注:这种转换会发生在第一次遇到加法运算在整数和字符串中进行的时候。考虑这两个例子:2+3+“年”、“年”+2+3。前例中,“2+3”部分会按照正常的数值运算进行,所以结果是“5年”。后例中“年”+2计算是会变成字符串“年2”,再“加”3依然是字符串+数值的操作,所以结果是“年23”。想要得到“年5”需要使用括号:“年”+(2+3)。
var message = "2018" + "年";
Yuu:数字+字符串的结果和字符串+字符串的结果是 相同的。因此我们看到2018和“year”连接的时候,2018使用字符串“2018”来代替。
Yuni:是这样。
Yuu:在TJS加法中,就算操作数的数据类型不同,像上例这样,TJS会自动转换为合适的类型。因此我们在计算的时候不用特别考虑数据类型。译者注:这种“不考虑”是相对的。TJS对类型的自动调整有时候会带来我们意想不到的结果,比如“2+void”,这种本身没有意义的运算却可以产生结果。
Yuni:这还是很方便的。
Yuu:嗯,下面来试一下吧。
Yuni:哦,我还想问一下…这样写行不行?
var message = year + "年" + month + "月";
Yuu:嗯,没问题。这里的话,year和month都会正确地转换为需要的类型。
Yuni:那这样的话…
var d = new Date();
var year = d.getYear(); // 将年份值作为初始值直接赋值给变量year
var month = d.getMonth() + 1; //将(月份值+1)作为初始值直接赋值给变量month
var day = d.getDate(); // 将日期值作为初始值直接赋值给变量day
var hour = d.getHours(); // 将小时值作为初始值直接赋值给变量hour
var minute = d.getMinutes(); // 将分钟值作为初始值直接赋值给变量mounte
var second = d.getSeconds(); // 将秒钟值作为初始值直接赋值给变量second
var message = year + "年" + month + "月" + day + "日" + hour + "時" + minute + "分" + second + "秒";
System.inform(message);
Yuni:这样可以吗?
Yuu:那,执行一下就知道了。
Yuni:嗯…嗯,怎么紧张起来了…
/执行结果/
\
Yuni:哇~很好地显示出来了呢😄
Yuu:嗯,很棒!😉
Yuni:这次可是努力了哦。
Yuu:哈哈,下次也要保持这样哦。
Yuni:嗯,下次也会努力的~
要点
- TJS中变量有5种类型:void、整数、实数、字符串、对象、二进制。除了二进制类型,其他5种的使用频率比较高。
- void表示“空”,对应其他语言的“null”、“None”等,代表什么都没有。它通常用于表示一种无法操作的状态,比如一个变量未被初始化、一个变量属于无法使用的状态等。
- 整数类型(整型)可以存储一个从-263到263-1中的整数。(多说一句,一个整数占64位,8字节。)
- 实数类型(实型)可以存储有理数,实数的存储位数比整数还多,因此表示范围也会更大。还有一点,实数在计算机中存储的值并不是这个值本身,而是一个十分接近它的值。这意味着,对实数每进行一次操作就会损失一定的精度。当操作的数量很多时,损失的精度就会不能被忽略了。另外,实数在比较的时候也要注意精度的问题,实数0.0和整数0在比较时有不相等的可能性。建议的比较方式是使用范围比较比如:abs(x-0) < 0.000001。等讲到内置方法时我们会更好地理解。
- 字符串用于一系列字符的表示。字符串中的内容需要使用成对的双引号或单引号括起来。
-
对象是类的实例,是一个复合类型。类和对象在实现时有不同的表达方法,我们先考虑类和对象最基本的使用。对象通常具有一些属性,我们可以读取或修改内部的属性值。它也具有一些方法,我们可以使用它定义的方法完成一些操作。如果说类定义的是一种操作模型,对象就是完成实际操作的实体。这样来看,
var d = new Date();
声明的d就是一个对象,它可以操作Date这个类定义的属性和方法,比如获取年份值d.getYear()
。很显然,“.”这个操作符就是说明从属关系的,表示我要用的是d
的getYear()
方法,不是d1
的。下一章会详细讲解类和对象的知识。 -
二进制类型很少会用到,这里忽略。
-
字符串的加法用于连接字符串,也可以连接字符串和另一个非字符串的内容,比如整数。在连接时,非字符串内容都会按照一定方法转换成字符串。在字符串与其他类型数据连接的时候,请务必注意以下的情况:
var s1 = 2 + 3 + '年'; // 5年
var s2 = '年' + 2 + 3; // 年23
var s3 = '年' + (2 + 3); // 年5
- 我们可以在声明变量的同时赋予它一个初始值。初始值可以是任意类型,只要符合使用需求即可。
拓展
转义字符
TJS的转义字符和其他语言如JavaScript是基本一致的。如果有相关的经验,这部分应该很容易理解。不过没有经验的小伙伴们也不用担心,它并不难理解。
首先,先说一下转移字符出现的原因。一个原因是字符串中可能会出现“字符串的终结符号”(单引号或双引号)。在正文中,我们提到对于出现双引号的字符串用单引号括起来,反之亦然。如果字符串中单引号和双引号都出现的话,单引号和双引号都不能直接用了。另一个原因是,字符串中存在一些控制字符,它们用来控制显示的格式。一些控制字符是无法直接表示的,然而它们又的确可以存在于字符串中。
为了很好地表示这些例外的字符,我们使用转义字符来处理。转义字符使用反斜杠“\”开始,后面接一个常规字符。两个字符整体代表了一个我们需要的字符。我们会使用的转移字符有:
- \’:单引号
- \”:双引号
- \:反斜杠
- \n:换行
- \r:回车
- \t:制表符
- \b:回退
- \f:分页符
- \v:垂直制表符
- \0:空字符(U+0000 NULL)
比如表示一个既有单引号又有双引号的字符串:
var s = '字符串既有\'单引号\',又有"双引号",用单引号括起来的话\"双引号\"也可以使用转义字符。';
System.inform(s);
额外提一句,在中文的单引号和双引号是不受转义字符限制的。