Learining TypeScript (一) TypeScript 简介
Learining TypeScript (一) TypeScript 简介
一、TypeScript出现的背景
在过去的几年里,基于JavaScript的Web应用的数量呈几何级数增长,虽然目前ES6(即ECMAScript2015,从ES6开始采用年份命名)的标准在2015年6月份已经发布了,增添了许多新的特性,例如:模块和类,以及一些实用的特性,例如Map,Sets,Generates,Promises等等,支持向后兼容,所有的老代码也可以正常运行,但目前为止还没有一个完全支持ES6标准的JavaScript代理,不论是浏览器还是服务器环境,所以开发者不得不将ES6代码向ES5转义,所以ES6标准的广泛应用,还需要一个漫长的过程。
为了解决JavaScript的维护和扩展问题,微软花了两年的时间开发出TypeScript,并在2012年10月公布了第一个公开的版本。它是JavaScript的一个超集,它与现存的JavaScript代码有非常高的兼容性,任何合法的JavaScript程序都是合法的TypeScript程序,另外它还给大型项目提供一个构建机制,TypeScript(以下简称ts)中加入了基于类(Class)的对象、接口和模块,采用面向对象编程的方式。至此ts就诞生了。
二、TypeScript的架构
学习的过程就是这样,当你学习一门新的东西的时候,总是要从基础知识开始学起,这样有利于你以后的学习,还有个作用是,给你以后的面试提供很大的帮助。
1、设计目标
我们可以从以下几点中了解到,决定TypeScript作为程序语言发展到今天这个形态的设计目标和架构:
- 对JavaScript结构的静态分析很有可能死错误的。微软(以下简称MS)的工程师们认为为了防止并排查一些运行时错误的最佳方式是,创造一种在编译期间进行静态类型分析的强类型语言,因此他们设计了一个语言服务层给开发者提供一些更好的工具。
- 与现存的JavaScript代码有非常高的兼容性。TypeScript作为JavaScript的超集,所有合法的JavaScript程序代码都是合法的TypeScript代码。
- 给大型项目提供一个构建机制。引入了类的对象、接口和模块,结合最佳的面向对象的编程,使代码更具可维护性和扩展性。
- 对于发行版本的代码,没有任何运行时开销。在使用TypeScript时,通常是将程序设计阶段和运行阶段区分开来的,通俗的讲就是说我们在设计程序时使用TypeScript代码,而运行时呢编译成JavaScript代码。为何要这样呢?原因很简单,比如在ts中有接口的概念,在js中是不存在也不支持接口的,那么ts编译器在编译出的js代码中也就不会声明也不会模拟这个特性。MS的Engineers提供了一些类似于代码转换(将TypeScript特性转变为JavaScript代码实现)和类型擦除(移除静态类型标记)的组件给ts的编译器,来产生纯净的JavaScript代码,类型擦除组件不仅移除了类型的标注,还移除了所有ts代码的所有的高级语言特性,比如接口等。
ts在编译时默认使用ES3标准进行编译,极大的提高了浏览器的兼容性,当然它也支持ES5和ES6的标准。一般情况下使用任意受支持的编译目标,我们都可以使用ts特性,但部分特性需要ES5或更高的版本版本作为编译目标的先决条件。
- 遵循当前以及未来出现的ECMAScript规范。ts不仅支持现有的js代码,而且也拥有兼容未来版本的能力,大多数的ts的新增特性都是基于未来的JavaScript提案,这样也意味着许多ts代码在将来甚至会变成合法的JavaScript代码。
- 成为跨平台的开发工具。MS使用Apache协议开源了TypeScript,并且它可以在所有的主流操作系统上安装和执行。
2、TypeScript组件
TypeScript语言内部主要被分为三层,每一层又被依次分为子层或者组件,如下图所示:
每一层都有不同的用途:
- 语言层:实现所有TypeScript的语言特性。
- 编译层:执行编译、类型检查,然后将TypeScript代码转换成JavaScript代码。
- 语言服务层:生成信息以帮助编辑器和其他工具来提供更好的辅助特性,比如IntelliSense(智能感知),这是微软提供的一种代码检查与提示服务么可以在编码时提供相关信息。
- IDE整合:为了利用TypeScript的特性,IDE开发者需要完成一些集成工作。
三、TypeScript语言特性
在介绍TypeScript语言特性之前,首要任务是要搭建开发环境,官方提供了一个在线编辑器http://www.typescriptlang.org/play/ 该编辑器如下图所示:
编辑器左侧编写TypeScript代码,右侧会自动编译成JavaScript代码,当然作为我们专业的programmer来说,很少会采用这种在线编辑的方式进行开发了,可以下载安装TypeScript的编译器,作为一个.Net Developer来说,我们可以时候用Visual Studio,从VS2015开始,自动集成了TypeScript的开发环境,如果是以下版本,需要去官方下载TypeScript插件,当然我们现在推荐你使用VS2017了。除了这些之外,如果想在其他操作系统中开发,OSX和Linux,那我们可以选择一些比较流行的编辑器,他们都会有TypeScript插件,比如Visual Studio Code(以下成为VS Code),Sublime等,这里我推荐VS Code,它较Visual Studio不同在于前者是IDE集成开发环境,而后者定义为Eidtor(编辑器),我们不需要去安装Visual Studio几十个G的安装包,而且VS Code已经提供了成千上万的插件供你使用,你自己也可以去开发自己的插件,如图所示:
微软大大一直以来都是那么的贴心。VS Code提供了各操作系统的版本,可以直接下载使用。
选择好我们的开发编辑器后,就要安装TypeScript,需要用到npm命令,但是在使用npm命令前,需要在开发环境中安装node.js,地址https://nodejs.org,找到对应的版本下载即可。验证是否安装成功,可使用
npm –version
查看npm版本
下面我们可以使用命令安装TypeScript了
npm install -g typescript
(-g)为全局安装,但是如果你是OS X用户,需要使用sudo命令,需要获取管理员权限,
sudo npm install -g typescript
可以使用 tsc -v 命令验证是否安装成功
Ok,至此我们的开发环境就搭建完成了。
现在我们创建一个test.ts文件,保存一个文件夹内,里面输入以下代码:
var t : number = 1;
然后切换到此文件夹内,执行
tsc test.ts
此时可以发现,在同目录下,会编译生成一个test.js文件。如图:
1、类型
我们已经知道,ts是js的超集,ts通过向js增加可选的静态类型声明来把js变成强类型语言,可选的静态类型声明可约束函数,变量,属性等程序实体,这样编译器和相应的开发工具就可以在开发过程中提供更好的正确性验证和辅助功能(比如IntellSense)。还可以让程序员对自己的和其他开发人员的代码表达他的意图,另外ts的类型检测在编译器运行并且没有运行时开销。
比如:
var counter; //未知(any)类型
var counter=0; //number类型(推断出的)
var counter:number; // number类型
var counter:number=0; // number类型
2、变量、基本类型和运算符
这部分简要说明,对ts的基本类型包括boolean、number、string、array、void和所有用户自定义的enum类型。所有的这些类型都是any类型的子类型。来看几种特殊的类型的用法:
- Array 和js一样,ts允许使用数组,array类型的声明有两种写法,
第一种:
var list:number[]=[1,2,3];
第二种是使用范型数组类型Array:
var list:Array<number>=[1,2,3];
- enum 枚举类型,为了更好的给一个数字集合命名,默认从0开始,当然你也可以手动设置成员的值,如:
enum Color{Red,Green,Blue};
var c:Color=Color.Red;
- any类型可以表示任意的JavaScript的值。
- void类型在某种程度上是any类型的对立面,即所有类型不存在的时候,你会在一个没有返回值得函数中看到他:
function warnUser:void{
alert("This is my warning message!");
}
- null 和undefined 。在JavaScript中undefined是全局作用域的一个属性,它会赋值给那些已被声明但是未被初始化的变量;null是一个字面量(不是全局对象的一个属性),他可以被赋值给那些表示没有值的变量。例如:
var TestStr; //变量声明但未初始化
alert(TestStr); //显示undefined
alert(typeof TestStr); //显示undefined
var TestStr=null; //变量声明,并且被赋值为null
alert(TestStr); //显示null
alert(typeof TestStr); //显示object
然而在TypeScript中,null和undefined不能当作类型来使用:
var TestStr:null; //错误,类型错误
var TestStr:undefined; //错误,找不到undefined
- var、let和const
在TypeScript中,当声明一个变量时,可以使用var 、let和const关键字:
var myNum:number=-1;
let isValid:Boolean=true;
const appid:string="0FDFD-8989-4CC3-9080-CSDJJFID7HJFD9";
var 声明的变量保存在最近的函数作用域中,如果不存在任何函数中则在全局作用域中。
let声明的变量保存在最近的比函数作用域小的块作用域中,如果不存在则在全局作用域中。
const关键字会创建一个保存在创建位置作用域中的常量,可以是全局作用域也可以是块作用域,这表明const是块作用的,关于作用域的知识会在后面进一步了解。
- 联合类型
TypeScript允许联合声明:
var path:string[]|sring;
path='/temp/log.xml';
path=['/temp/log.xml', '/temp/info.xml'];
path=1;
此时path=1;会报类型错误,因为在声明时并未对path进行number的合法声明。
- 类型守护
可以在运行时使用typeof或者instanceof运算符对类型进行验证。TypeScript语言服务会在if区域寻找这些运算符,然后对应地更改类型:
var x: any = { /* ... */ };
if(typeof x === 'string') {
console.log(x.splice(3, 1)); // 错误,'string'上不存在'splice'方法
}
// x 依然是 any 类型
x.foo(); // 合法
在这段代码中,我们首先声明了一个any类型的变量x,随后在运行时通过typeof运算符对x进行了类型检查。如果x的类型为string时,我们就会尝试调用被认为是x的一个成员的splice方法。TypeScript语言服务可以读懂在条件语句中使用typeof的用法。TypeScript会自动推断出x一定是string类型,然后告诉我们splice方法不存于string类型上。这种特性被称为类型守护。
- 类型别名
TypeScript允许使用type关键字声明类型别名:
type PrimitiveArray = Array<string|number|boolean>;
type MyNumber = number;
type NgScope = ng.IScope;
type Callback = () => void;
但是不建议在一个大的项目团队中使用这种别名,可维护性会降低。
- 环境声明
环境声明允许在TypeScript 代码中创建一个不会被编译到 JavaScript中的变量。这个特性是用来促进与现有 JavaScript 代码、DOM(文档对象模型),还有BOM(浏览器对象模型)结合而设计的。让我们看一个例子:
customConsole.log("A log entry!"); // 错误
如果你尝试调用customConsole对象上的log方法,TypeScript会告诉我们customConsole对象未被声明:
// Cannot find name 'customConsole'
出现这种情况并不令人意外。但是,有时候我们希望调用一个未被定义的对象上的方法,比如window对象上的console方法。
console.log("Log Entry!");
var host = window.location.hostname;
当访问 DOM 或 BOM 对象时,我们没有遇到错误,是因为这些对象已经在一个特殊的 TypeScript 文件(被称为声明文件)中被声明了。可以使用declare操作符创建一个环境声明。
在下面这段代码中,我们会声明一个被customConsole对象实现的接口。然后使用declare操作符在作用域中增加一个customConsole对象:
interface ICustomConsole {
log(arg : string) : void;
}
declare var customConsole : ICustomConsole;
然后就可以在没有编译错误的情况下使用customConsole:
customConsole.log("A log entry!"); // 成功
TypeScript 默认包含一个名为lib.d.ts的文件,它提供了像 DOM 这种 JavaScript 内置库的接口声明。
使用.d.ts结尾的声明文件,是用来提高 TypeScript 对第三方库和像 Node.js 或浏览器这种运行时环境的兼容性的。
- 运算符
运算符包括:算术运算符、比较运算符、逻辑运算符、位运算符、以及赋值操作符。
这些运算符在这里不再赘述,如果有开发的基础的话,这些应该都会清楚。
3、流程控制语句
包含选择语句、循环语句和分支语句
if 、if else 、?、switch case 、while 、do while 、for in(类似freach)、for循环,这些语句是我们再熟悉不过的东东了,也不再赘述了吧。
4、函数
关于函数,就像JavaScript一样,TypeScript可以通过具名或匿名方式创建,根据具体情况,选择合适的方式声明即可。如:
function greet(name?:string):string{
return "Hi"+name;
}//这是一个带有返回值的具名函数;
//匿名函数
var greet=function(name?:string):string{
return "Hi"+name;
}
如果不想使用函数的语法,还可以有另一种选择,使用箭头(=>)操作符并不适用function关键字,如:
var greet=(name?:string):string=>{
return "Hi"+name;
}
在这个例子中,我们还可以给greet变量添加上匹配匿名函数的类型:
var greet=(name?:string)=>string=function(name:string):string{
return "Hi"+name;
}
*注意:当处于类的内部时,如果使用箭头函数(=>)语法将会改变this操作符的工作机制,会在后面的学习中详细讨论。
已经学习了如何将一个变量强制描述为指定形式的函数。这在我们使用回调函数时是十分有用的。
function sume(a:number,b:number,callback(result:number)=>void){
callback(a+b);
}
5、类
在ES6中添加了基于类的面向对象编程语法,由于TypeScript是基于ES6的,所以我们可以开始使用基于类的面向对象的语法了。TypeScript的编译器会负责将TypeScript代码编译为兼容主流浏览器和平台的JavaScript代码。
class
Person {
fullname: string;
constructor(firstname: string, lastname: string) {
this.fullname = firstname + " " + lastname;
}
hello(name?: string) {
if (name) {
return
"Hi! " + name + "! My Name is " + this.fullname;
} else {
return
"Hi! My Name is" + this.fullname;
}
}
}
var person = new Person("Allen", "Choi");
var msg = person.hello("Allen");
alert(msg);// "Hi !Allen! My Name is Allen Choi";
var msgnull = person.hello();
alert(msgnull);//"Hi! My Name is Allen Choi"
在上面的例子中,我们定义了一个Person类,有三个成员:一个fullname属性,一个构造函数constructor和一个greet方法。当在TypeScript中声明类时,所有的属性和方法都是公共的。
当在对象内部访问对象成员时,我们都加上了this操作符,这表明这是一个成员访问操作,我们使用new操作符构造了一个Person实例,这会调用类的构造函数,按照定义对实例进行初始化。
为了兼容ES3和ES5,TypeScript中的类会编译为JavaScript中函数
var Person = /** @class */ (function () {
function Person(firstname, lastname) {
this.fullname = firstname + " " + lastname;
}
Person.prototype.hello = function (name) {
if (name) {
return
"Hi! " + name + "! My Name is " + this.fullname;
}
else {
return
"Hi! My Name is" + this.fullname;
}
};
return Person;
}());
var person = new Person("Allen", "Choi");
var msg = person.hello("Allen");
alert(msg);
var msgnull = person.hello();
alert(msgnull);
6、接口
在TypeScript中,可以使用接口来确保类拥有指定的结构。
interface LoggerInterface {
log(arg: any): void;
}
class
Logger
implements LoggerInterface {
log(arg) {
if (typeof console.log === "function") {
console.log(arg);
} else {
alert(arg);
}
}
}
在这个例子中,我们定义了一个LoggerInterface接口,和实现了一个Logger的类,Typescript也允许使用接口来约束对象,这样可以帮助我们避免很多小错误。例如下面的例子中:
interface UserInterface {
name: string;
password: string;
}
var user: UserInterface = {
name:"",
pasword:""
//password 遗漏错误属性
}
7、命名空间
命名空间,又称内部模块,被用于组织一些具有某些内在联系的特性和对象。命名空间能够使代码结构更清晰,可以使用namespace和export关键字,在TypeScript中声明命名空间。
namespace
Geometry {
interface VertorInterface {
/*...*/
}
export
interface Vertor2dInterface {
/*...*/
}
export
interface Vertor3dInterface {
/*...*/
}
export
class
Vertor2d
implements VertorInterface, Vertor2dInterface {
/*...*/
}
export
class
Vertor3d
implements VertorInterface, Vertor3dInterface {
/*...*/
}
}
var vector2dInstance: Geometry.Vertor2dInterface = new
Geometry.Vertor2d();
var vector3dInstance: Geometry.Vertor3dInterface = new
Geometry.Vertor3d();
在上面例子中,我们声明了一个包含了Vector2d、Vector3d类和VectorInterface、Vector2dInterface、Vector3dInterface接口的命名空间。
*注意:命名空间内的VectorInterface并没有export关键字,所以在命名空间外部,我们访问不到它。
8、综合运用
下面是一个使用了模块、类、函数和类型注解的案例:
module
Geometry{
export
interface
Vector2dInterface{
toArray(callback:(x:number[])=>void):void;
length():number;
normalize();
}
export
class
Vector2d
implements
Vector2dInterface{
private
_x:number;
private
_y:number;
constructor(x:number,y:number){
this._x=x;
this._y=y;
}
toArray(callback:(x:number[])=>void):void{
callback([this._x,this._y]);
}
length():number{
return
Math.sqrt(this._x*this._x+this._y*this._y);
}
normalize(){
var
len=1/this.length();
this._x*=len;
this._y*=len;
}
}
}
var
vector:Geometry.Vector2dInterface=new
Geometry.Vector2d(2,3);
vector.normalize();
vector.toArray(function(vectorasArray:number[]){
alert('x:'+vectorasArray[0]+'y:'+vectorasArray[1]);
})
四、小结
这一部分的内容主要是介绍了一些关于TypeScript的基础知识,相信有开发经验的人对这些并不感冒,不管你是用了两分钟看完了,还是用了20分钟看完了,希望你能有一点点的收获,内容有书本上的内容,也有网上摘的,如有不对的地方,请多包涵指正。从头看到尾,或许你越来越感觉它的语法以及一些特性,像极了C#,对于.Net 开发人员来说应该是再熟悉不过了。后面的内容会持续更新,也希望自己能坚持下来吧。
Learining TypeScript (一) TypeScript 简介的更多相关文章
- TypeScript:TypeScript 百科
ylbtech-TypeScript:TypeScript 百科 TypeScript是一种由微软开发的自由和开源的编程语言.它是JavaScript的一个超集,而且本质上向这个语言添加了可选的静态类 ...
- typescript和coffeescript简介
typescript 1.什么是typescript?和JavaScript有什么关系? 1.它是一门独立的语言,实现了自己的编译器 2.它的目标代码是JavaScript(很多语言的目标代码是机 ...
- [TypeScript] Installing TypeScript and Running the TypeScript Compiler (tsc)
This lesson shows you how to install TypeScript and run the TypeScript compiler against a .ts file f ...
- 6、什么是TypeScript、TypeScript的安装、转换为.js文件
1.什么是TypeScript (本人用自己的理解梳理了一下,不代表官方意见) TypeScript:Type+ECMAScript6 TypeScript是一种预处理编程语言,遵循es6标准规范,在 ...
- 【TypeScript】TypeScript 学习 5——方法
在 JavaScript 中,有两种方式定义方法. 1.命名的方法 function add(x,y){ return x+y; } 2.匿名方法 var myAdd = function(x,y) ...
- 【TypeScript】TypeScript 学习 4——模块
前端数据验证在改善用户体验上有很大作用,在学了之前的知识的时候,我们很可能会写出以下代码: interface StringValidator { isAcceptable(s: string): b ...
- 【TypeScript】TypeScript 学习 3——类
在 EcmaScript 6 中,我们将会拥有原生的类,而不是像现在通过原型链来实现.使用 TypeScript 我们能提前体验这一特性. 首先来看看一个简单的例子: class Greeter { ...
- 【TypeScript】TypeScript 学习 2——接口
在 TypeScript 中,接口是用作约束作用的,在编译成 JavaScript 的时候,所有的接口都会被擦除掉,因为 JavaScript 中并没有接口这一概念. 先看看一个简单的例子: func ...
- 【TypeScript】TypeScript 学习 1——基本类型
TypeScript 是 JavaScript 的超集,TypeScript 经过编译之后都会生成 JavaScript 代码.TypeScript 最大的特点就是类型化,因此才叫做 TypeScri ...
随机推荐
- <2014 04 26> 《Coders at Work编程人生:15位软件先驱访谈录》
什么是老派程序员?调试只用printf,关心数据结构,先整体或先局部,不知道OO.IDE.TDD.BDD等等为何物.Ken Thompson,Jamie Zawinski,Joe Armstrong, ...
- PHP去除所有的空格
1.去除两边的空格 trim($arr) 2.正则匹配去除所有的空格 preg_replace('# #','',$goodid)
- 详细介绍Redis的几种数据结构以及使用注意事项(转)
原文:详细介绍Redis的几种数据结构以及使用注意事项 1. Overview 1.1 资料 <The Little Redis Book>,最好的入门小册子,可以先于一切文档之前看,免费 ...
- Pandas 通过追加方式合并多个csv
常用合并 通常用pandas进行数据拼接.合并的方法有: pandas.merge() pandas.concat() pandas.append() 还有一种方式就是通过 pd.to_csv() 中 ...
- 手势识别:GestureDetector
当用户触摸屏幕的时候,会产生许多手势,例如down,up,scroll,filing等等,我们知道View类有个View.OnTouchListener接口,通过重写他的onTouch(View v, ...
- mysql 如何找出两张表之间的关系
分析步骤: #1.先站在左表的角度去找 是否左表的多条记录可以对应右表的一条记录,如果是,则证明左表的一个字段foreign key 右表一个字段(通常是id) #2.再站在右表的角度去找 是否右表的 ...
- Docker下载地址(官网实在太慢)
官网因为大家都懂得各种原因,访问简直慢如狗. 找到一个网站,下载很快. 如下: https://oomake.com/download/docker-windows
- ThreadLocal 示例
ThreadLocal, 从字面意思上看是本地线程. 但实际上它是一个线程本地变量.它的功能就是为每一个使用该变量的线程都提供一个变量值的副本, 从而使得不会与其他线程的副本冲突. 与使用synchr ...
- python16_day17【Django_session、ajax】
一.Session 1.settings.py SESSION_ENGINE = 'django.contrib.sessions.backends.db' # 引擎(默认) SESSION_COOK ...
- mysql增量恢复的一个实例操作
通过防火墙禁止web等应用向主库写数据或者锁表,让主库暂时停止更新,然后进行恢复 模拟整个场景 1.登录数据库 [root@promote 3306]# mysql -uroot -S /data/3 ...