TypeScript入门学习笔记

TypeScript 是微软出品的一个 JavaScript 的超集,在 js 的技术上实现了一些最新的 ES 规范标准。现在前端三大框架之一的 Angular 已经开始使用 TypeScript,我也赶紧来学习一下。

这篇文章是在慕课网 JoJozhai 老师的课程下的学习笔记,算是一个入门指引,推荐大家去学习,课程链接:TypeScript入门

认识 TS

TS 必须要被编译器编译成 JS 才能才浏览器运行,自己练习可以使用在线编译器,推荐一个官方出的编译器:http://www.typescriptlang.org/play/index.html

本地编译使用 npm 包

npm i -g typescript

然后使用 tsc 命令来转换 .ts 文件到 .js。

也可以使用 IDE 的编译功能,同时使用代码提示功能。

字符串新特性

1、多行字符串:

var content=`
这是多行
字符串
`

2、字符串模板:在多行字符串里用表达式插入变量或调用方法

var name = 'ts';
var getName = function () { return 'ts' };
console.log(`hello ${name}`)//变量
console.log(`hello ${getName()}`)//表达式
console.log(`
<div>
<span>这里是内容</span>
</div>
`)//方便拼接字符串

3、自动拆分字符串:根据表达式自动进行切割

function test(template,name,age){
console.log(template)
console.log(name)
console.log(age)
}
var name='ts';
var getAge=function(){ return 18 }
test`my name is ${name},i'm ${getAge()}`;
//得到结果:["my name is ",",i'm ",""],ts,18

在 test() 方法里,第一个参数是整个表达式被拆分的值(作为数组),第二个参数是第一个表达式的值,第三个参数是第二个表达式的值。

参数新特性

1、参数类型:在参数后面使用冒号指定类型(如果不指定类型,ts 会自动推断类型并作出提示)

var name:string = 'ts';

any 类型可以作为任何类型
string 字符串
number 数字
boolean true 或者 false
void 声明方法的返回值,表明方法不需要任何返回值

function test(name:string):void{
~~~
}

变量和方法可以声明类型,也可以给方法的参数声明类型。

自定义类型:

在 ts 里可以通过 class 类 或者 interface 接口自定义类型。

//定义类型
class Person {
name: string;//这是属性
age: number;//这是属性
}
//定义变量
var zhangsan:Person =new Person();
//此时 zhangsan 有了两个属性,分别是 name 和 age

2、参数默认值:在参数后面用等号指定参数默认值

var name:string='ts';

给方法的变量指定默认值:

function test(a:string,b:string,c:string){
console.log(a);
console.log(b);
console.log(c);
}
//此时调用的时候如果参数数量不对就会报错
test('x');//报错
//如果指定第三个参数为默认值,则可以只传前两个参数
//注意:带默认值的参数只能放在最后
function test(a:string,b:string,c:string='z'){
console.log(a);
console.log(b);
console.log(c);
}
test('x','y');//x,y,z

3、可选参数:在方法的参数后面用问好表示此参数是可选参数

//注意:可选参数不能在必选参数前面
function test(a:string,b?:string,c:string='z'){
console.log(a);
console.log(b);
console.log(c);
}
test('x');//x,undefined,z

函数新特性

1、Rest and Spread 操作符:用于声明任意数量的方法参数

function test(...args){
//这里的...就是 Rest and Spread 操作符
//args 就是一个数组
args.forEach(function(arg){
console.log(arg)
})
}
//调用的时候传入多少个参数都是合法的
test(1,2,3);
test(4,5,6,7);

反向使用 Rest and Spread 操作符:

function test(a,b,c){
console.log(a);
console.log(b);
console.log(c);
}
//根据方法参数个数来调用,这里有3个
var args1=[1,2];
test(...args1);//1,2,undefined
var args2=[4,5,6,7];
test(...args2);//4,5,6

2、generator 函数:控制函数的执行过程,手动暂停和恢复执行。ES6通过 yield 关键字来实现这个功能。

//generator 函数通过在 function 后面加一个星号来表示
function* doSth(){
console.log('start');
yield;//关键字,相当于断点
console.log('finish');
}
doSth();//这样调用不会有效,必须声明成一个变量,再调用 .next()
var func=doSth();
func.next();//此时打印 start 即停止
func.next();//此时完整打印完毕

3、析构表达式:将对象或数组拆解成任意数量的变量

function getStock(){
return {
code:'IBM',
price:100
}
}
//ES5方法:
var stock = getStock();
var code = stock.code;
var price = stock.price;
//使用析构表达式:
var { code , price } = getStock();
console.log(code);//IBM
console.log(price);//100

注意:{}里的变量名要与函数内的对象名一致。如果要另起新的名字:

var { code:codex , price } = getStock();
console.log(codex);//IBM

对于嵌套的对象重复使用析构表达式即可:

function getStock(){
return {
code:'IBM',
price:{
price1:200,
price2:400
}
}
}
var { code , price:{price2} } = getStock();
console.log(code);//IBM
console.log(price2);//400

针对数组的析构表达式:

var arr=[1,2,3,4,5];
var [n1,n2]=arr;
console.log(n1);//1
var [,,n3,n4]=arr;
console.log(n3);//3
var [n1,n2,...others]=arr;
console.log(others);//3,4,5

作为方法的参数使用:

var arr=[1,2,3,4,5];
function test ([n1,n2,...others]){
console.log(n1);//1
console.log(n2);//2
console.log(others);//3,4,5
}
test(arr);

表达式与循环

1、箭头表达式:用于声明匿名函数,消除传统匿名函数的 this 指针问题

var sum=(a1,a2)=>a1 + a2;//对于只有一行的函数,可以省略大括号和 return
//对于多行的写法:
var sum=(a1,a2)=>{
return a1 + a2
}
//没有参数:
var sum=()=>{}
//单个参数:
var sum= n => {
console.log(n)
}

2、for of 循环

//forEach()
var arr=[1,2,3,4,5];
arr.desc='good';//属性
arr.forEach(value => console.log(value));//1,2,3,4,5;没有 good
//for in 循环,得到数组的键
//在 js 里任何对象或者集合都是键值对的集合,键就是属性的名字,值就是属性的值。
for(var n in arr){
console.log(n);//0,1,2,3,4,desc
console.log(arr[n]);//1,2,3,4,5,good
}
//for of 可以在循环中 break,忽略属性,也可以循环字符串
for(var n of arr){
console.log(n);//1,2,3,4,5;没有 good
if(n>3) break;
console.log(n);//1,2,3
}
for(var n of 'good'){
console.log(n);//g,o,o,d
}

面向对象特性

1、class 类

定义

class Person {
//类的属性
age;
eat(){
console.log('i'm eating')
}
}
//实例化
var p1= new Person();
p1.age='11';
p1.eat();

访问控制符

public:默认,可以在类的内部和外部访问
private:私有,只可以在类的内部访问
protected:受保护的,在类的内部和子类被访问到

class Person {
private age;
private eat(){
console.log(age);//类的内部可以访问
}
}

构造函数

类的构造函数其实就是类的内部一个特殊的方法,只有在类被实例化的时候只被调用一次。可以用来指定实例化的时候的参数。

class Person {
constructor(){
console.log('haha')
}
age;
eat(){
console.log(age);//类的内部可以访问
}
}
var p1= new Person();
p1.age='11';
p1.eat();

构造函数的使用:

class Person {
name;
constructor(name:string){
this.name=name;
}
eat(){
console.log(this.name);//类的内部可以访问
}
}
//上面的类也可以写成:
class Person {
constructor(public name:string){
//这里的 public 不能省略
}
eat(){
console.log(this.name);//类的内部可以访问
}
}
var p1= new Person('ts');
p1.eat();

类的继承

通过 extends(声明继承关系) 和 super(调用父类的构造函数) 关键字

class Person {
constructor(public name:string){
}
eat(){
console.log(this.name);//类的内部可以访问
}
}
class Teacher extends Person {
code:string;
work(){
}
}
var t1=new Teacher('Jay');
t1.eat();
//父类
class Person {
constructor(public name:string){
}
eat(){
console.log("i'm eating");//类的内部可以访问
}
}
//子类
class Teacher extends Person {
constructor(name:string,code:string){
super(name)//子类的构造函数必须要调用父类的构造函数
this.code=code;
}
code:string;
work(){
super.eat();//调用父类的其他方法
this.doWork();
}
doWork(){
console.log("i'm working")
}
}
var t1=new Teacher('Jay','1');
t1.eat();

2、泛型 generic,指参数化的类型,用于限制集合的内容

class Person(){
}
var workers:Array<Person>=[];//表示这个数组只能放 Person
workers[0]=new Person()

3、接口 interfa,用于建立某种代码约定,使得其他开发者在调用某个方法或者创建新的类的时候必须遵循接口所定义的代码约定。

//用作方法的参数的类型声明的时候,调用类的时候要遵循接口所约定的属性
interface IPerson(){
name:string;
age:number;
}
class Person(){
constructor (public config:IPerson){
}
}
var p1=new Person({
name:'aa',
age:12
})
//所有实现接口的类必须要实现接口里面的方法
interface Animal(){
eat()
}
class Dog implements Animal(){
eat(){
console.log('meat')
}
}

4、模块 module,将代码分割为可重用的单元。在 ts 里一个文件就是一个模块。export 和 import 关键字,不同文件可以同时有引用和暴露属性、方法和类。

a.ts

var name;//不对外暴露
export var people;//对外暴露

b.ts

import { people } form './a'
console.log(people)

5、注解 annotation,为程序的元素(类、方法、变量)加上说明,供指定工具或框架使用。

6、类型定义文件:
*.d.ts 帮助开发者使用已有的 js 工具包,如 jQuery。
类型定义文件来源:https://github.com/DefinitelyTyped/DefinitelyTyped
查找类型定义文件工具:https://github.com/typings/typings
PS: TypeScript 现在已经可以通过 npm install @types/库名 来安装类型定义文件了,这样可以把ts项目所需要的定义文件描述到npm包里,维护起来更加方便。

总结

这里只是一个入门介绍,可以在使用 Angular 的时候结合官方文档进行深入学习。