对象和接口-2:常见用法
1. 创建资源
开始实验之前,您需要先创建实验相关资源。
- 在实验室页面,单击创建资源。
- (可选)在实验室页面左侧导航栏中,单击云产品资源列表,可查看本次实验资源相关信息(例如IP地址、子用户信息等)。
说明:资源创建过程需要3~5分钟(视资源不同开通时间有所差异,ACK等资源开通时间较长)。完成实验资源的创建后,您可以在云产品资源列表查看已创建的资源信息,例如:子用户名称、子用户密码、AK ID、AK Secret、资源中的项目名称等。
实验环境一旦开始创建则进入计时阶段,建议学员先基本了解实验具体的步骤、目的,真正开始做实验时再进行创建。
资源创建成功,可在左侧的资源卡片中查看相关资源信息以及RAM子账号信息
2. 实验环境操作指南
在本系列实验中,有两种方法可以进行操作。一种是控制台方式,另一种是远程桌面的方式。接下来我们分别介绍这两种操作方式。
控制台方式
使用控制台方式操作实验,上手比较简单,对网络带宽的要求也不高。但是在编辑代码时,需要使用Vim工具进行文本编辑。对于初学者来说使用Vim工具需要熟悉其操作模式。
进入控制台环境
资源创建成功后,我们在右侧选择切换到Web Terminal。
切换到dev用户
本次实验的开发环境部署在dev用户的~/web目录中。因此我们执行这两条命令即可进入实验环境
su dev cd ~/web
Vim工具的用法
vim是一个命令行下的文本编译器。使用vim编辑文件时。我们只需要通过快捷键,而不需要鼠标就可以对文本文件进行编辑。但是这种文本编辑器的用法和常见的图形界面编辑器使用习惯差别较大。接下来我们简单介绍vim的使用。
3.1 进入Vim
在命令行中输入vim即可进入操作界面,这时的Vim没有打开任何文件。
vim
3.2 Vim的三种模式
和普通编译器不同的是,Vim包含了三种操作模式。分别是命令模式,编辑模式,末行模式。接下来我们来简单介绍一下三种模式的用法。
3.3 命令模式
在刚进入界面的时候,vim默认状态为命令模式。这种模式下,无法编辑文件,键盘输入也不会在屏幕上有任何显示,这种情况往往会让使用者感到困惑。这时候我们可以输入大写的ZZ,即可退出Vim。
3.4 编辑模式
我们继续输入vim回到编辑器。在命令模式下我们按下小写的i。此时我们会发现下部的提示已经变成了插入。这表示vim已经进入了编辑模式。
在编辑模式下我们就可以像正常的编辑器一样编辑文件。此处我们输入hello world。
在编辑完成之后,如果我们想退回命令模式,只需要按ECS键即可。按下该按钮之后我们会发现下部的插入提示消失了,这就表示vim回到了命令模式。
3.5 末行模式
回到命令模式之后,我们按下:键,这时下部的提示会变成:,这就表示vim进入了末行模式。在末行模式下,我们同样使用快捷命令操作vim,但是和命令模式不同的是,末行模式中输入的命令会显示的屏幕的最后一行。
接下来我们继续输入w demo.txt并按回车。会提示显示为如下内容。表示上面的内容已经保存到了demo.txt中。
最后我们按:q,该命令也可以退出vim。
4. 编辑index.js文件
4.1 创建新文件
当我们希望编辑特定文件时,我们可以输入vim 文件名。这时候在下部会看到"index.ts" [新]。表示vim自动创建了新文件。
vim index.ts
4.2 复制粘贴
在编辑模式下,vim同样可以使用ctrl+v进行粘贴。我们按i进入编辑模式之后,将下列内容粘贴到vim中。
//vim编辑模式和命令模式的常用命令: //在编辑模式中:可以使用 上 下 左 右 按键移动光标 //在命令模式中:可以使用 h j k l 命令移动光标 //在编辑模式中:可以使用退格或者DEL键删除字符 //在命令模式中:可以使用 x 命令删除字符 //在命令模式中:可以使用 dd 命令删除整行文字(谨慎使用!) //在命令模式中:可以使用 ggdG 命令删除全部文字(谨慎使用!) //在命令模式中:可以使用 u 命令撤销操作 //在命令模式中:可以使用 ctrl + r 命令重做操作。
4.3 文件内容的查找
在命令模式下,除了按:命令之外,还可以使用/命令进入末行模式,通过/进入末行模式之后,输入相关的内容即可进行全文检索。我们在命令模式下输入/dd。
光标就会移动到相关字符上。
4.3 文件的保存和放弃
当我们编辑完成之后,可以在命令模式中通过ZZ命令直接保存并退出编辑器,也可以通过在末行模式中通过:w单独保存文件。如果我们希望通过末行模式保存并退出,可以使用:wq。
但是需要注意的时,如果文件在修改之后没有保存,是无法通过:q退出的。如果编辑过的文件是只读属性也无法通过ZZ退出。这时我们就可以使用:q!命令放弃所有的编辑内容,强制退出vim。
远程桌面方式
使用远程桌面方式进行实验是,可以使用VS Code编译器进行代码的编写和操作,相对控制台方式更加的直观。但是这种方式对网络带宽的要求比较高。
进入网页环境
1.1 进入远程桌面
资源创建成功后,我们在右侧选择切换到远程桌面。
1.2 启动浏览器
在远程桌面页面中,点击Chromium网页浏览器。
登录RAM用户
2.1 打开网页
浏览器启动后会默认打开阿里云的RAM用户登录页。在登录页面中我们点击下一步按钮。
2.2 获取密码
接下来我们需要输入RAM用户的密码。密码显示在实验控制台左侧,我们点击子用户密码右侧的复制按钮。
复制完成后,我们在用户密码框中按Ctrl + V 复制密码,然后点击登录按钮
进入ECS的远程连接。
3.1 进入ECS控制台
登录成功后,页面跳转到控制台,我们在控制台的搜索框中输入ECS,然后点击云服务器ECS进入云服务器控制台。
3.2 进入远程连接界面
在ECS控制台中,我们找到实验创建的ECS,点击右侧的远程连接按钮。
3.3 选择VNC远程连接
在远程连接中选择通过VNC远程连接中的立即登录如果没有显示该选项,则可点击展开其他登录方式按钮。
登录VNC远程连接
4.1 初始化VNC密码
初次登录VNC远程连接时需要先设置VNC密码。点击重置VNC密码按钮。
输入两次新的VNC密码,并点击确认。
4.2 登录VNC
VNC密码设置成功后,输入密码并点击确认。
4.4 进入图形界面
VNC登录成功后会看到实验ECS的登录界面,在登陆界面中我们点击DEV用户图标
4.5 在图形界面中登录
在密码框中输入默认登录密码Dev12345。即可进入图形实验环境
使用VS Code编辑器
登录图形实验环境之后,接下来我们来启动VS Code 编辑器。
5.1 进入应用程序列表
首先我们点击界面的下方的显示应用程序按钮。
5.2 启动VS Code
在应用程序列表中选择最后一页
然后点击VS Code应用图标
5.3 选择文件
在VS Code 编译器中,左边区域为文件列表,可以选择要编辑的文件
5.4 编辑文件
在VS Code中,右上区域为文件编辑区,可以进行文件内容编辑
5.5 操作终端
在右下区域的终端选项卡,为控制台区域,可以进行命令输入执行
3. 扩展属性
在上一个实验中我们学习了对象类型的基本用法,和元组类型相比,对象类型的每一个属性都有名字,同时属性值的限制比元组类型更加严格。因此在TypeScript中被大量的使用。
在使用对象类型时,不但会出现某些属性值可能为空的可选属性。也会出现希望对象中可以保存一些未知属性以满足扩展性的需求,例如人员统计表中可能会存在某些扩展属性和特殊情况。在这种情况下我们就需要一种能扩展对象类型的属性的方法。
- 扩展属性的定义
在对象类型中,我们可以使用索引签名,的方式来扩展属性。索引签名的语法为[名称:key类型]:属性类型。添加之后索引签名之后,我们就可以在对象初始化,属性赋值,还是属性读取时,操作未知属性。
需要注意的时,添加了索引签名之后,由于可以操作未知属性,因此一旦属性拼写错误时,TypeScript编译器无法做出错误提示。我们修改index.ts文件为如下内容。
var user: { name: string, age: number, male: boolean, [p: string]: any }; user = { name: "ALIYUN", age: 20, male: true, address: "HANGZHOU" }; user.phone = "138000000" user.height = 1.83 console.log(user); console.log("phone:", user.phone); console.log("phone:", user.phone1);
在终端选项卡输入如下命令编译并查看。
tsc && node index.js
- 索引签名的用法
在使用索引签名的时候有一些事情是需要注意的:
- 首先一个对象类型中,只能有一个索引签名。
- 索引签名中的名称可以任意定义,不会影响对象的定义。
- 如果不限制扩展属性值的类型,索引签名中的属性类型,可以设置为any。关于any类型在后面的实验中会有详细讲解。
- 如果需要通过属性类型来限制扩展属性值的类型。需要注意的是,属性类型必须包括对象中所有属性的类型。
我们修改index.ts文件为如下内容。
var user: { name: string, age: number, male: boolean, [任意: string]: string | number | boolean }; user = { name: "ALIYUN", age: 20, male: true, address: "HANGZHOU" }; user.phone = "138000000" user.height = 1.83 console.log(user);
在终端选项卡输入如下命令编译并查看,
tsc && node index.js
- number型的索引签名
索引签名的key类型除了可以设定为string之外,还可以设置为number和boolean。其中number的用法比较常见。当我们使用该类型的索引签名时,需要注意的是:
- number型的索引签名的属性只能使用[]方式访问。
- 在访问时可以使用[数字]的形式,也可以使用[“数字”]的形式。
- number型的索引签名的属性类型,不需要包含包括对象中所有属性的类型。
我们修改index.ts文件为如下内容。
var code: { name: string, count: number, init: boolean, [任意: number]: string }; code = { name: "数字中文对照表", count: 3, init: true, 0: "零" }; code[1] = "一" code["2"] = "二" console.log(code); console.log(code["1"]); console.log(code[2]);
在终端选项卡输入如下命令编译并查看,
tsc && node index.js
4. 属性的遍历
通过之前实验的学习我们了解到,对于对象类型的元素,我们也可以使用[]关键字进行访问。除此之外TypeScript还提供了几种可以遍历对象类型属性的方法。
同时在上一个步骤中我们学到的可扩展的属性时,可扩展的属性的使用非常灵活,例如我们可以让用户在网页上输入他想添加的扩展属性。但是这种灵活性也以为这单纯的通过在代码中写死属性名进行访问的方式无法访问到未知的属性名称。这时候我们就需要采用遍历的方式找到对象中的全部属性。
- for in方法遍历
第一种方法为和数据遍历类似的for in方式,这种方法下,可以获得对象中的全部属性名称,然后通过[]语法获得对象的属性值,我们修改index.ts文件为如下内容。
var obj: { name: string, age: number, male: boolean, [p: string]: any }; obj = { name: "ALIYUN", age: 20, male: true, address: "HANGZHOU" }; obj.phone = "138000000" obj.height = 1.83 console.log(obj); for (var n in obj) { console.log(n + ":" + obj[n]) }
在终端选项卡输入如下命令编译并查看,
tsc && node index.js
- Object.keys方法遍历
除了for in语法之外。我们还可以用Object.keys方法获得对象类型的全部属性值数组。然后再通过遍历属性值名称数组的方式。获得全部的属性。我们修改index.ts文件为如下内容。
var obj: { name: string, age: number, male: boolean, [p: string]: any }; obj = { name: "ALIYUN", age: 20, male: true, address: "HANGZHOU" }; obj.phone = "138000000" obj.height = 1.83 console.log(obj); var names: string[] = Object.keys(obj); for (var n of names) { console.log(n + ":" + obj[n]) }
在终端选项卡输入如下命令编译并查看,
tsc && node index.js
- Object.values方法遍历
和我们在数组实验中学到的遍历方法不同,对象类型并不支持for of遍历方法。作为替代在ES2017的版本之后TypeScript提供了Object.values方法用来直接遍历对象的属性值。
需要注意的时,这种方法无法读取的属性的名字,因此该用法并不非常常见,例如可以用一个索取签名对象,用来用当作用户成绩册。然后使用Object.values获得并计算总分数。
首先我们修改tsconfig.json文件设置属性值为如下
"target": "es2017"
接下来我们修改index.ts文件为如下内容。
var score: { [p: string]: number } = {}; score["中文"] = 95; score["英文"] = 86; score["数学"] = 90.5; score["编程"] = 87.5; var arr: number[] = Object.values(score); var sum = 0; arr.forEach(s => sum += s); console.log("sum = " + sum)
在终端选项卡输入如下命令编译并查看,
tsc && node index.js
5. 类型的串行化
串行化(Serialization)是指将复杂得元素转换成字符串或者二进制数据串,当我们需要将对象保存到本地,或者通过网络进行传输得时候,都需要将元素进行串行化。
与串行化对应的是反串行化(Deserialize),当我们需要将本地文件或者网络数据还原成元素时,就需要对字符串或者二进制串进行反串行化。在接下来的两小节我们将学习如何在TypeScript中对基本类型,数组,对象和函数进行串行化和反串行化。
- 对象类型到string
在之前的实验中我们学习了string类型的时候了解到。绝大多数的TypeScript对象都具有toString方法,可以将对象转化成字符串。但是在对象类型中toString方法并不能返回我们需要的结果,无论什么类型的对象,调用toString()只会返回[object Object]。
如果是单纯的需要调试对象,我们可以使用console.log()方法将对象转换成字符串。我们修改index.ts文件为如下内容。
var user: { name: { first: string, last: string } score: { n: string, s: number }[] sayHello: () => void }; user = { name: { first: "Ali", last: "yun" }, score: [{ n: "语文", s: 95.5 }, { n: "数学", s: 100 }, { n: "编程", s: 84 }], sayHello: () => { console.log("hello") } } console.log(user.toString()) console.log(user)
在终端选项卡输入如下命令编译并查看。
tsc && node index.js
- 对象类型到JSON字符串
通过上面的步骤,我们可以看到通过console.log方法,虽然可以将对象类型转换成字符串,但是如果对象类型中包含了函数属性,转换后的的字符串中会包含[Function: 函数名]。如果我们希望单纯的保存数据属性,我们就需要使用JSON格式的字符串。
JSON是一种轻量级的数据交换格式。他的格式和TypeScript中的string,number,boolean,对象和数组类型的语法非常类似。同时可以将对象和数组类型进行嵌套组合。
当我们希望把一个对象或者数组类型转换成JSON格式时,可以使用JSON.stringify方法。我们修改index.ts文件为如下内容。
var user: { name: { first: string, last: string } sayHello: () => void }; user = { name: { first: "Ali", last: "yun" }, sayHello: () => { console.log("hello") } } console.log(user) console.log(JSON.stringify(user))
在终端选项卡输入如下命令编译并查看。
tsc && node index.js
- 复杂类型的转换
通过观察上面的步骤的转换会发现,生成的JSON字符串和TypeScript的对象代码非常相似,同时函数属性不会被转换。但是需要注意的是。在JSON字符串中,对象中属性的名称字段的前后需要添加""。
JSON.stringify除了可以转换对象类型之外。还可以转换对数组类型,已经对象和数组组合的复杂类型。接下来我们再来转换一个复杂的对象和数组嵌套元素。我们修改index.ts文件为如下内容。
var user: { name: { first: string, last: string } score: { n: string, s: number }[] }[]; user = [ { name: { first: "Ali", last: "yun" }, score: [{ n: "语文", s: 95.5 }, { n: "数学", s: 100 }] }, { name: { first: "阿里", last: "云" }, score: [{ n: "计算机", s: 80 }, { n: "编程", s: 84 }] } ] console.log(user) console.log(JSON.stringify(user))
在终端选项卡输入如下命令编译并查看。
tsc && node index.js
6. 类型的反串行化
接下来我们再来学习如何进行元素和JSON之间的反序列化功能。
- JSON字符串到对象类型
当我们希望从JSON字符串转换成TypeScript元素时,可以使用JSON.parse方法。需要注意的是当字符串中包含"时,我们有两种方法可以处理,第一种是使用''来定义字符串,第二种是使用\"代替字符串中的"。我们修改index.ts文件为如下内容。
var json: string = '{\"name\":{\"first\":\"Ali\",\"last\":\"yun\"}}' var user: { name: { first: string, last: string } }; user = JSON.parse(json) console.log(user)
在终端选项卡输入如下命令编译并查看。
tsc && node index.js
- 反串行化的类型
当我们通过JSON.parse方法进行反串行化时,由于字符串中的内容并不可知,因此该方法返回的类型也是不可知的。我们可以用任何的类型去接受反串行化的返回结果。这也会导致TypeScript的类型检查失效。
在下面的例子中我们将一个对象JSON字符串反串行化,然后保存到数组类型中,TypeScript并没有报错。因此在使用反串行化的时候需要格外注意。我们修改index.ts文件为如下内容。
var json: string = '{\"name\":{\"first\":\"Ali\",\"last\":\"yun\"}}' var arr: number[]; arr = JSON.parse(json) console.log(arr)
在终端选项卡输入如下命令编译并查看。
tsc && node index.js
- 反串行化的错误处理
和串行化不同的时,反串行化方法JSON.parse接受的参数是一个字符串。字符串参数就不可避免的会存在格式不正确的问题。当输入到JSON.parse方法的string参数无法正常的反串行化时,会触发TypeScript的异常。
在下面的例子中,我们使用一个不完整的JSON字符串进行反串行化,这时候异常会被触发,而异常的触发会打断应用正常的处理流程,导致程序退出。这一点是我们特别要注意的。我们修改index.ts文件为如下内容。
var json: string = '{\"name\":{\"first\":\"Ali\",' var user: { name: { first: string, last: string } }; user = JSON.parse(json) console.log("JSON.parse之后的业务流程。")
在终端选项卡输入如下命令编译并查看。
tsc && node index.js
- 异常处理
因此在实战中,在使用JSON.parse进行反串行化时,我们需要使用try catch来处理可能会出现的异常。具体做法为通过try{}来包裹JSON.parse,同时在catch (SyntaxError) {}中处理可能出现异常的情况。我们修改index.ts文件为如下内容。
var json: string = '{\"name\":{\"first\":\"Ali\",' var user: { name: { first: string, last: string } }; try { user = JSON.parse(json) } catch (SyntaxError) { user = { name: { first: "默认", last: "默认" } } } console.log(user)
在终端选项卡输入如下命令编译并查看。
tsc && node index.js
实验地址:https://developer.aliyun.com/adc/scenario/9326a8249a9842708bec939c2cfaf915