Ts学习深入浅出
前言:
“我们为需要构建和维护大型JavaScript程序的团队设计了TypeScript,以满足他们的需求。TypeScript可帮助他们在软件组件之间定义接口,并且帮助理解现存JavaScript库的行为。同时,使用TypeScript的团队可以将代码构建成动态加载的模块,以减少命名冲突的问题。TypeScript可选的类型系统使开发者们可以使用一些高效的开发工具和最佳实践:静态检查,基于符号的导航,代码补全和代码重构. 摘自——TypeScript语言特性”
基本配置环境:
此部分直接开始我们的干货之旅,以下是作者本人经过亲身实践,采用图文并茂的方式给大家详细讲解基本上手配置环境的过程。
- 如果你用的是VsCode,那么作者为你感到高兴,因为说明你与作者站到了一起。废话不多说,先上干货:
看见上图你就知道你Ts的环境已经完成,下面你需要的是撸起袖子书写你第一句HelloWorld吧!
2.如果你使用其他代码编译器或者使用的是OS X 或 Linux操作系统,可以下载一个NPM模块,如果你不熟悉npm也不需要担心,到目前为止,只需要知道它是Node包管理的标准并且是Node.js的默认包管理工具即可。为了能使用npm,你需要先在开发环境中安装node.js。可以在Node.js的官方网站上https://node.js.org/找到相应...。(写了这么多骚气的告诉你,无论你用哪一种node已经无孔不入。已经不再是你的可选项,赶紧下载一个去吧!)对了! 别忘了 npm install -g typescript
3.继续在命令行环境下键入 tsc -init 进行初始化,
你会发现根目录下多了 tsconfig.json 的文件,记录了编译成JS的选项
打开该文件,会发现主要选项已经帮你设置好了,比较常用的设置是
”target” : 编译为何种规范,一般设置为 ES5 或者 ES2016/2017
“outdir” : 输出目录
“alwaysStrict” : 打开严格模式 (‘use strict’)
命令行下输入 code . 打开VSCode进入该目录,按下 Ctrl+shift+B 快捷键会进行编译,初次编译会选择编译模式,如下图所示:
我们在此处选择监视模式,这样基于以上的几点就完成了Ts的基本配置任务
类型
经过作者(*中保)在前面一段云里雾里的讲解不知道给大家讲懂了多少,如果还有细节不理解的地方可以联系作者本人,接下来就要介绍类型:
- 先撸一把概念:首先我们已经了解了TypeScript是JavaScript的超集,TypeScript通过向JavaScript增加可选的静态类型声明来把JavaScript变成强类型的程序语言。可选的静态类型声明可约束函数,变量,属性等程序实体,这样编译器和相应的开发工具就可以在开发过程中提供更好的正确性验证和帮助功能,大家看到这的朋友如果是满嘴我靠,我靠,我靠。说的什么,感觉好专业一句听不懂。作者本人为了让大家接受到最专业的类型解释语句,是在自己的书中,结合视屏学习过程中抽离了精华,进行了语句本身的重构。嘻嘻看到这里如果还觉的少给我装逼有干货没?说了这么多请看作者自己实际操作的下图:
写到这里还有很多朋友问我,你最喜欢Ts的什么地方,目前来讲:1.强类型特性能让程序员对自己和其他开发团队成员在代码中表达出意图 2.TypeScript类型检测在编译时期进行并且没有运行时的开销。
此处温馨提示一下,let与const关键字在TypeScript1.4中就可以使用了,但只有在编译目标为ECMAScript6或者以上时才可用,大家如果想使用还需要手动在package.json中手动配置下方可使用。
2.接下来就是我们讲述类型的重中之重了,既然本章节是讲类型,先带大家了解下Ts的基本类型(此处与JS略有不同希望大家仔细阅读)
- 基本类型有boolean,number,string,array,void和所有用户自定义的enum类型。(此处大家要重点了解的是所有上述讲到的类型在TS中,都是一个唯一的顶层的AnyType类型的子类型,any关键字代表这种类型。让我们看一下这些原始类型。下面是我本人整合的一些内容基本都在这里了)
- 此处不知道大家有没有什么想法?(反正我是没有),接下来就给大家介绍一种联合类型(以图中的内容为主)。
联合类型用来声明那些可以存储多种类型值的变量。在上面这个例子中,我们声明了一个可以存储一个(字符串)或者一组路径(字符串数组)的变量Lzb。在例子中,我们也对这个变量进行了赋值,将字符串和字符串的数组合法地赋值给了这个变量。然而,当试图将一个数字赋值给它时我们遇到了一个编译错误,因为这个联合类型并没有声明number为它的合法类型。
- 此处我给大家介绍一部分函数的内容(此部分内容个人认为尤为重要):且看下图
下面是将Ts转换为JS后的内容继续看下图:
类
在ECMAScript6(即最新版本的JavaScript)中,添加了基于类的面向对象编程语法。由于TS是基于ES6的,所以开发者如今就已经可以开始使用基于类的面向对象的语法中了。TS的编译器会负责将TS代码编译为兼容主流浏览器和平台的JavaScript代码。
让我们来看一个在TS中定义类的例子:(如下图所示)
简单来讲,在上面的例子里,我们一起定义了一个名为Character的新类。这个类有三个成员:一个名为fullname的属性,一个构造函数constructor,和一个greet方法。当我们在Ts中声明类时,所有的属性和方法默认都是公共的。或许你可能已经留意到,当(在对象内部)访问对象内的成员时,我们都在前面加上了this操作符,this操作符表明了这是一个成员访问操作(好吧,排除前面一大段日常装逼操作,返璞归真的来说,如果你在类内部想定义一个属性,如果你不在构造函数constructor中this给其赋值的话,用有道词典的话来讲属性“fullname”没有初始化器,也没有在构造函数中明确指定。)简单来讲就会报错。别急还没说完(我们使用new操作符构造了Character类的一个实例,这会调用类的构造函数,按照定义对实例进行初始化)
注意:为了兼容ECMAScript3 和 ECMAScript5,TS中的类会被编译为JavaScript中的函数。
函数
在学习这部分内容之前必须先隆重介绍下我们的函数:函数是任何TypeScript应用程序中的基础功能块,它们非常强大,我们最开始接触函数概念应该是在数学当中,记得当时讲解的是:函数是执行某项特定功能的模块。同样这样的概念,也可以延伸到我们的编程当中。
- 函数声明和函数表达式:
函数在TS中分为了显示指定函数名称的(命名函数)和不显示指定名称的(匿名函数)我们看下图代码来具体理解
人生若只如初见,你会感觉什么都很美好!就和上面这两种函数一样(那么的熟悉,那么的相似),但是它们的行为并不一样,解释器会首先在代码解释阶段执行函数声明,而另一方面,除非函数表达式被赋值。否则就不会被执行。(好吧,到这里我相信我需要再用白话来解释下,简单的来讲如果你仅仅是函数声明,像图中的第一个函数的形式的话,你的调用可以发生在前后都可以,但是如果是第二种则会发生变量提升的过程,所以如果你是在之前去调用的话,结果就和图中的一样画了个红线。)
- 函数的类型
先看下面截图我们再做解释:
在上述函数中,我们定义了参数name的类型(string)和返回值类型(string).有时候我们不只需要定义函数中元素的类型,还需要定义函数本身的类型。让我们再看下下面这个截图:
在上述例子中,我们声明了变量greetUnnamed 及其类型。greetUnnamed的类型是一个只包含一个名为name的string类型参数,在调用后返回类型为string的函数。在声明了这个变量之后,一个完全符合变量类型的函数被赋值给了它。我们也可以声明greetUnnamed的类型,并在同一行中将一个函数赋值给它,而不是分割成两行,比如下面这个例子:
就像上面这个例子,之前的代码片段中同样声明了变量greetUnnamed和它的类型。我们也可以在同一行中把一个函数赋值给这个变量,被赋值的函数类型必须与变量类型相同。
- 有可选参数的函数
与JavaScript 不同,调用函数时传的参数的数量或类型不符合函数中定义的参数要求时,TypeScript编译器会报错。让我们通过一个代码示例来证明这点:
上述函数名为Add并包含三个number类型参数:LZB,Bar,LZBbar。如果调用这个函数时没有完整地传入三个参数,会得到一个编译错误,提示提供的参数与函数声明中的参数无法匹配。
在一些场景下,我们也许想调用这个函数且不提供所有的参数。TypeScript提供了一个函数可选参数的特性,可以帮助增加这个函数的灵活性。可以在TypeScript中通过在函数参数后追加一个字符?,指定函数参数是可选的。更新一下前面的函数,将LZBbar参数从必选参数修改为可选参数。
请看清楚,我们在此将参数LZBbar的名称更改为了LZBbar?,并在函数内部检测LZBbar参数是否被提供。修改后,在我们提供两个或者三个参数调用这个函数时,TypeScript编译器不再抛出错误。
值得注意的是,可选参数必须位于必选参数列表的后面。
- 有默认参数的函数
当函数有可选参数时,我们必须检测参数是否被传递了(就像上一个例子中那样)。
在一些场景中,应为一个可选参数设置默认值。可以使用内联if结构重写Add函数(从上一个代码片段中)
这个函数并没有错误,但是可以通过提供LZBbar参数的默认值,来代替标记其为可选参数,以改善其可读性。
我们只需要在声明函数签名时使用 = 操作符提供一个默认值,即可指定函数参数是可选的。TypeScript编译器会在JavaScript输出结果中生成一个if结构,在LZBbar参数没有传递给函数时设置一个默认值。
- 有剩余参数的函数
我们已经了解了如何使用可选和默认参数来改善函数调用。让我们再回到上一个例子中:
我们在之前的学习过程中已经学习到了如何调用Add函数并传递两个或者三个参数,但是如果希望允许其他开发者传递四个或者五个参数呢?不得不再添加两个额外的默认或者可选参数。那如果希望允许开发者传递任意数量的参数呢?解决方案是使用剩余参数。剩余参数语法允许把不限量的参数表示为一个数组(这一做法非常类似于原生JS中的arguments):
看一下上述代码片段,我们用一个参数LZB替换了之前的参数。你会注意到,参数LZB前面有一个三个点的省略号。一个剩余参数必须包含一个数组类型,否则就会出现编译错误。我们现在可以以任意数量的参数调用Add函数:
虽然没有具体的参数数量限制,理论上可以取数字类型的最大值。但实际上,这依赖于如何调用这个函数。
JavaScript函数有一个被称为arguments的内建对象,这个对象可以通过arguments局部变量取到。arguments变量是一个非常像数组的对象,包含了调用函数时的所有参数。(如果我们检查JavaScript的输出会发现,TypeScript遍历arguments参数,以便将所有参数添加到foo变量中:)
对这个额外的针对函数参数的遍历存在一些争议。虽然难以想象这个额外的遍历是否会成为一个性能瓶颈,但是如果你认为这可能会对应用程序带来性能问题,应考虑不使用剩余参数而是只使用一个数组作为函数参数。
上述代码只有一个包含了number类型的数组。调用API会和剩余参数有一些不同,但是可以去除对函数参数列表进行遍历的操作:
- 函数作用域
一些低级语言(比如C语言)包含了底层内存管理特性。在拥有更高层抽象的编程语言(比如TypeScript)中,当变量被创建时,内存就已经被分配,并且在它们不被使用时会被清理掉。这个清理内存的过程被称为垃圾回收,由JavaScript运行时的垃圾回收器实现。