飞道科技

飞道科技文档总汇

TypeScript 基础

介绍

以下文字摘自官网

TypeScript is a typed superseet of JavaScript that compiles to plain JavaScript, Any browser, Any host. Any OS. Open source.

还有一句话

JavaScript that scales.

大致翻译是说:TypeScript 是 JavaScript 的一个带类型的超集,可以编译成JavaScript。

JavaScript

介绍中提到,TypeScript可以编译成JavaScript。事实上,根本没有一个解释器可以直接执行TypeScript,如果要想执行它,当须先编译成JavaScript方可。这也说明,如果想用好TypeScript,是需要有JavaScript基础的,事实上使用TypeScript的人,基本上都是JavaScript转过来的。至于为什么弃J从T,当由JavaScript的不足说起。

优点

  1. 浏览器原生支持

    现今没有一款浏览器不支持JavaScript的,虽然有禁用JavaScript一项设置,但几乎不会有人进行这样的禁用设置。展望将来,也能预见,不会有浏览器会停止支持JavaScript。也就是说,在浏览器里面,如果要写脚本,首选就是JavaScript。

  2. 简单

    包括语言易学(至少入门级的如此),开发调试方便。你所需要的只是一个几乎脑脑必备的浏览器+任意一款文本编辑器(甚至没有文本编译器也可以),无须复杂的环境安装和配置。

  3. 弱类型

    这是语言特性,弱类型使用简单,更灵活多变。

缺点

  1. 弱类型

    前面提到,这是JavaScript的一项优点,但它是一个双刃剑,更是一个大大的缺点,因为是弱类型,在进行编译的时候,弱类型会影响编译优化(所以我们在编写JavaScript代码的时候,尽量不要让一个变量一会儿是数字类型,一会儿是字符串类型)。因为弱类型,使得无法方便地通过查看代码确定一个变量的类型,这在代码维护上带来了无穷无尽的麻烦,有些前人的代码,简直惨不忍睹(其实别人看你的代码没准儿也是这感觉)。这给我们的感觉就是无法通过JavaScript做大的软件项目,因为软件项目大到一定量的时候就无法继续维护下去了。

  2. 异步回调

    因为JavaScript的事件驱动机制,会有大量的回调函数,如果回调函数里再嵌套的有其它的回调函数,一层层的回调函数调下去,就到了回调地狱,如果你曾有过此等遭遇,那么恭喜你,因为你这时才能更深刻理解Promise和Async functions!很多人因此离开了JavaScript。

  3. 不能操作本地资源

    在浏览器里,JavaScript能做的事情非常有限,只能操作页面上的Dom元素,响应用户的鼠标或键盘事件。很多事情类似操作本地磁盘上的一个Word文档等做起来都很吃力,甚至产生了一系列的“浏览器插件”来完成这样的一些功能(很不幸地,这些插件还需要限定特定的浏览器)。

  4. this

    JavaScript中的this跟其它开发语言中不太一样,很多有多年开发经验的人员一直搞不清楚JavaScript中的this是个什么东西。它竟然是可变的,这简直太恐怖了!

解决方案

如何在保留JavaScript优点的基础上弥补一下它的缺点?弃而投靠其它开发语言不是一个好的解决办法,那样你会遇到另外其它的问题。

解决方案:Node.js+TypeScript+Function,其中Node.js(包括nw.js,electron)用来让JavaScript具有操作本地资源的能力。TypeScript让复杂项目变得可维护,用它来做复杂项目变为可能。只使用函数(如果是回调,则使用箭头函数)而不使用,使我们几乎不用关心this的问题。

认识TypeScript

进入正题,我们来看一下TypeScript的代码:

function sayhi(name: string) {
	console.log(`hi, ${name}!`);
}

上面的三行代码声明了一个函数,函数名为sayhi,这个函数有一个参数,形参名字为name,形参的类型为string.这个函数没有返回值。如果我们调用了该函数,像这样:

sayhi('feidao');

它会在控制输出一行文字:hi, feidao!;

变量

声明一个变量的关键字为let,声明变量的同时可以给它赋上初始值。如下所示

let v = 1;
++v;

常量

声明一个常量的关键字const,事实上TypeScript中的const并非一定的常量,它仍然可以改变。比如引用类型的jsObject或是jsArray都可以改变,它只是不能被重新赋值罢了。

const v = 1;
++v;	// Error: Cannot assign to 'v' because it is a constant or a read-only property.
const arr = [1, 2, 3];
arr.push(4);	// 没有错误,可以正常使用

注意看以上两种情形,第一种情况因为有自增运算++,包括前自增,在JavaScript里它都属于重新赋值,所以TypeScript编译器会对这些已经声明过为常量对象进行重新赋值的代码行报错,赋值的操作还包括=+=,-=,*=,/=,|=,^=,>>=,<<=等。

const声明的常量与Object.freeze有相近之处,都是希望它们不能被改变,只不过它们的差别是const声明的常量如果是Object,包括Array,虽然不能被重新赋值,但实际上还是可以修改的,而Object.freeze正是针对Object类型的。

个人建议全部用const声明常量,从来不要用let,甚至var声明变量。甚至如果有必要,对const声明的Object类型的常量再加以Object.freeze限定就更好了。

接口

接口在强类型开发语言中,接口是指实体把自己提供给外界的一种抽象化物,由一套陈述、功能、选项、其它表达程序结构的形式、以及程序师使用的程序或者程序语言提供的数据组成。它通常用于一些去实现接口中定义的一些方法,在TypeScript中,我们也可以这么干,但接口对我们来讲,主要用来定义一些数据结构。像前面最开始的示例

function sayhi(name: string) {
	console.log(`hi, ${name}!`);
}

如果我们把它修改一下,就用到了接口:

interface Person {
	name: string;
	age: number;
}

function sayhi(person: Person) {
	console.log(`hi, ${person.name}! your are ${persoon.age} years old.`);
}

我们在例子中定义的接口,它的主要使用就是给这个函数的调用者一个调用参数的类型限定。我们在调用这个函数的时候就需要像下面这样调用它

sayhi({name:'feidao', age: 5});

它不仅用来定义函数的参数类型,有时候我们也用它来定义函数的返回值类型

function fun(name: string, age: number) {
	return {
		age,
		name
	};
}

TypeScript中的类跟Java,C#中的类几乎一模一样。如果你有这方面的编程经验,这一部分可以跳过了。

我们这里对TypeScript中的类做一个介绍,但我们在项目开发过程中基本是不会写类,我们在项目中只写函数,但我们可能会用到类,比如Date,所以我们简单介绍一下,做个了解就好,只要会使用就足够了。

声明

声明一个简单的类,它的名字叫A,并且有一个受保护的方法,名字叫method_a

class A {
	protected method_a() {
		// todo
	}
}

一个类都有构造函数constructor(原谅我用构造函数而没有用构造方法这个词,因为大家似乎都这么叫),但有些时候我们不写构造函数,像上例一样,其实它还是有构造函数的,只是你看不到罢了:

class A {
	constructor() {
	}
	protected method_a() {
		// todo
	}
}

但它没有析构函数,GC会帮我们回收不用的内存资源。

接下来我们来从它派生一个类,名字叫B,它有一个公有方法叫method_b.

class B extends A {
	constructor(param: string) {
		super();
	}
	public method_b() {
		this.method_a();
	}
}

在B的所有方法里,我们都可以调用A的所有受保护protected以及公开public的方法。需要通过this来调用。

使用

使用一个类的时候,我们需要先将这个类构造出来一个对象,然后使用这个对象调用它的成员函数成员变量

const a = new A();
a.method_a();	// ts error, but it could be called indeed.
const b = new B('lalala');
b.method_b();

注意一定不要将一个类的成员函数当作回调函数去调用,因为这会改变this。如

const b = new B();
setInterval(b.method_b, 2000);	// Dot not use like this

如果遇到这种情况,要这么用它:

const b = new B();
setInterval(() => {
	b.method_b();	// Use like this
}, 2000);

其它

诸如派生接口、静态方法等知识,因为我们极少使用,为了减轻大家的学习负担,不在这里介绍,如果有兴趣,请稳步各大搜索引擎.