typeScript简介
- javaScript的超集
- 遵循ES6
- 兼容ES5
- typeScript线上编译器: http://www.typescriptlang.org/play/index.html
- typeScript本地编译器:
npm install -g typescript
;tsc -version
可以查看是否安装成功 - 编译ts文件生成js文件:
tsc hello.ts
字符串
多行字符串
多行字符串用反引号`表示,可以在``中直接换行
var a = `<div>
<span>hello</span>
</div>`
字符串模板
可以用${}在多行字符串里面使用表达式,
- 字符串模板只能再多行字符串里面使用,
在普通的字符串里,比如"aaa"无法使用;
var name="李飞";
var age = 26;
var html = `
<div>
<span>我的名字是${name}</span>
<span>我的年龄是${age}</span>
</div>
`
自动拆分字符串
当用多行字符串来调用一个方法的时候,多行字符串里面的
表达式会被作为方法的参数传进去;
function test(template, name, age) {
console.log(template);
console.log(name);
console.log(age);
}
let name1 = "lifei";
let age = 22;
test`我的名字是是${name1},年龄是是${age}还有别的`;
上面的name1,和age被作为参数传到了函数test里面;输出的template是一个数组;
["我的名字是是", "年龄是是"", "还有别的"]
变量
指定变量类型
- 声明变量
在声明变量时,可以为变量添加类型.比如number,string ,boolean,Array;
如果不想限制变量的类型可以使用any;
如果后面赋值的类型不对会报错,但是这里报错的人是typescript,
如果编译成了js,可以正常编译,并且不报错;
let name: string = "lifei";
let isman: boolean = true;
let a: number = 123;
let age: any = 666;
let list: Array<number> = [1, 2, 3]; //数组类型,里面的元素是number;
let list: number[] = [1, 2, 3]; //数组类型,里面的元素是number;
- 函数中声明返回值和参数
function test(name: tring) :string{
return "123";
}
括号里面的是声明函数的参数类型,括号后面的是声明返回值的类型;
如果是没有返回值就用 :void
function a(age: number) :void{
console.log(a)
}
- 自定义类型
变量声明的类型可以是自定义的类(也就是构造函数)
class Person {
name: string;
age: number;
}
var zhangsan :Person = new Person();
- 推测类型
在typeScript环境中,如果变量的声明没有声明类型也没有any.那么typescript会根据
变量的第一个值.来推测变量的数据类型;
var a="lifei" //typescript默认a的类型是string;
变量默认值;
- 普通的变量默认值
let name: string = "lifei";
- 函数的变量默认值
typescript是强类型语言,声明了一个有三个参数的函数,如果调用的时候只传两个,typescript会报错;
而不是和js一样把第三个参数默认成undefined;如果有了默认值,就可以少传参数了;会直接使用默认值;
一般来说有默认值的参数会放在最后;
function test(a: string, b: string, c: string='lifei'){
console.log(a);
console.log(b);
console.log(c);
}
test("aa", "bb", "cc") //输出"aa", 'bb', 'cc';
test('aa', "bb") //输出"aa", 'bb', 'lifei';
可选参数
在函数的参数后面添加问号"?", 可以设定这个参数可选
function(a: string, b? :number) {
console.log(a)
console.log(b)
}
可选参数和有默认值的参数都要放在必选,无默认值的参数的后面;
函数新特性
Rest and Spread: ...
rest and Spread操作符是三个点: "...",代表任意数量的参数;
- 在声明函数中使用
如果在声明函数中作为默认参数,则代表任意数量的参数数组
function func1(...args) {
args.forEach(function(arg){
console.log(arg)
})
}
func1(1, 2, 3);
func1(8, 9, 10, 11, 12);
- 在调用函数中使用
在调用函数中使用,后面跟一个数组.代表把数组里的元素当做函数的参数挨个传入
function func1(a, b, c) {
console.log(a);
console.log(b);
console.log(c);
}
var arr1 = [1, 2];
var arr2 = [5, 6, 7, 8, 9]
func1(...arr1); //输出1,2, undefined
func1(...arr2); //输出5, 6, 7;
- 事实上rest and spread操作符在调用函数中使用,并没有在typescript中实现
这是ES6里面的方法.在typescript中使用会报错,同样的解析后可以正常使用;
generator函数
控制函数的执行过程,手动的暂停或恢复代码的执行.类似于打断点的行为;
- 声明generator函数,在function后面加星号"*";
function* doSometing(){}
- 打断点,在需要暂停的位置加上yield,类似于return;暂时停止;可以跟返回值;
- 函数运行并不会执行函数里的代码,而是返回一个运行对象,
var a= doSometing()
;
执行这个对象的next方法,才会运行函数,到断点,再次运行到下一个断点;a.next();
; - 返回值
var d = a.next().value;
; - 这是ES6语法,typescript暂时不支持,会报错.但是不影响编译;
function* doSometing() {
console.log("start");
yield "这里是返回值"; //暂停,类似打断点
console.log("finish")
}
var func1 = doSomething(); //此时函数并不执行,而是返回一个执行对象
func1.next(); //开始执行,输出"start", 运行到yield停止;
func1.next(); //再次开始执行,输出'finish'
箭头表达式和循环
箭头函数
箭头函数使用箭头"=>"来代替关键字function比如:
function aa(){}
aa() => {}
- 箭头函数最常用的地方是匿名函数,比如setTimeout,filter,setInterval的回调函数
setTimeout((a, b) => {
console.log(a);
console.log(b);
}, 1000)
- 箭头函数的匿名函数有一些简写操作
比如:单行匿名函数
setTimeout((a, b) => a+b, 1000)
//等同于
setTimeout(function(a, b){
return a+b;
}, 1000)
或一个参数的情况
setTimeout( arg => console.log(arg), 1000); //省略了括号();
箭头函数的this
箭头函数修改了传统js中一个this的指向.就是在外层this指向一个不是window的对象,
此时异步调用了一个函数,在这个函数里this指window,这个特性造成了一定的麻烦;
而在箭头函数中这里的this被修改为和外层的this一样的对象;
var Persion = function(){
this.name = "lifei"
setTimeout(function(){
console.log(this.name); //这里指window.name.输出undefined;
}, 1000)
}
var Persion2 = function() {
this.name="lifei";
setTimeout( () => {
console.log(this.name) //这里指new Rersion2()出来的对象,输出"lifei";
}, 1000)
}
for of循环
数组的forEach循环只能循环数组,并且不能用break打断;
for of循环是ES6特性,且被typescript支持;
for of循环则可以循环数组,对象,字符串,支持break和continue;
var aa = [1, 2, 3, 4, 5, 6]
for (var k of aa) {
if (k >= 2 && k <= 3) {
continue;
}
console.log(k); //输出1,4,5,6;
}
面向对象特性
类
声明
类的声明要用class关键字.实例化用new;
类的属性和方法都可以直接声明;在函数中或实例中用this来调用;
- 在编译之后类的方法是放在原型里面的,属性是和构造函数里面的代码放在一起的;
class Person{
age: number;
public name: string = "lifei";
constructor(age: number) {
console.log(age);
}
public eat() {
console.log("i am eating");
}
}
var a = new Person(12);
类的访问控制符
访问控制符: public(公开), private(私有), protected(受保护)
- public声明的属性可以在类的外面,实例化之后由实例调用.类的属性默认是public;
- private声明的属性只能再类里面用this调用(比如this.name).不能在类的外面用实例调用;
- protected声明的属性不能在外面调用,但是可以在子类里面调用;
构造函数constructor
- 在构造函数里的代码只会在实例化的时候执行一次;
- 构造函数只是一个实例化的时候向类里面传递参数的入口.
- 构造函数的参数并不会成为类的属性,除非给参数添加访问控制符.
说白了consstroctor构造函数只是一个入口,外层向类里面传递参数的入口;
让类可以直接使用外面封装的属性方法;
类的属性和方法应该在构造函数的外面直接声明;
class Person{
name: string;
constroctor(age: number){
console.log(age)
console.log(this.name);
}
}
var a = new Person(12); //这里传递的12,只是输出了而已,a并没有age属性,只有name属性;
class Person{
name: string;
constroctor(public age: number){
console.log(age);
console.log(this.name);
}
}
var b = new Person(12) //这里的b既有name属性,又有age属性;
类的继承
- extends声明继承关系
class Person{
name: string;
constroctor(age: number){
console.log(age)
console.log(this.name);
};
eat() { console.log("eating")}
}
class Emx extends Person {
}
var emx1 = new Emx(12); //这里的emx1是类Emx的实例,原型Person的实例;
- super调父类的函数;
如果在子类中有自己的构造函数,那么在执行自己的代码之前必须先执行一次父类的构造函数super(),就是这么规定的;
如果在子类中要用到父类的方法,就用super["方法名"]来调用;
class Person{ //父类
name: string;
constroctor(age: number){
console.log(age)
console.log(this.name);
};
eat() { console.log("eating")}
}
class Emx extends Person { //子类
school: string;
constructor(age: number, school: string){
super(age); //用super()执行父类的构造函数;
this.school = school;
};
work() {
super.eat(); //调用父类的eat方法;
}
}
var emx1 = new Emx(12, "北街"); //这里的emx1是类Emx的实例,原型Person的实例;
泛型(generic)
用来指定一个集合的数据类型
var workers: Array<Person> = [];
//workers数组里的元素只能是Person类型实例化出来的对象,或者是Person的实例化出来的对象的子类;
接口(Interface)
接口用来简历某种代码约定,使得其他开发者在调用某个方法或者
创建新的类时必须遵循接口所定义的代码约定;
简单来说就是定义接口的时候,规定了一定的属性,方法;
一个类使用这个接口,那么这个类就要也有这些属性和方法;
- 定义一个接口
interface IPerson {
name: string;
age: number;
}
- 作为函数的参数的接口使用
class Person {
constructor(public config: IPerson){}
}
var p1 = new Person({name: "lifei", age: 13});
//因为类Person的构造函数的参数使用了接口IPerson,在用new 创建Person实例的时候,
//构造函数的参数就必须有name,age属性;
- 作为类的接口使用
interface Animal{
eat();
}
class Sheep implements Animal{
eat(){
console.log("eating")
}
}
//类Sheep使用了接口Animal,那么他就必须要有函数eat;
模块
模块可以帮助开发者将代码分割成可重用的单元,开发者可以决定
将模块中的类,方法,变量,暴露出去供外部使用,或者只在模块内部使用
在typescript里面一个文件就是一个模块;
export 导出, import导入;
export var prop1; //在别的文件就可以用import引入这个变量
import prop1; //在本文件中引入这个变量;
注解(annotation),又名装饰器
注解为程序的元素(类,方法,变量)加上更加直观的说明信息,
这些信息与程序的业务逻辑无关,而是给框架或工具的说明.;
import {Component } form "@angular/core";
@Component({ //这个就是注解(装饰器)
selector: "app-root",
templateUrl: './app.component.html',
styleUrl;['./app.component.css']
})
export class AppComponent {
title = "app works";
}
//上面的装饰器的作用是告诉angular4.0框架这个组件的html模板
和css文件到哪里找,selector: 'app-root'是指这个组件在html中
是用<app-root></app-root>标签标示的;
简而言之就是原来的script,link里面的信息用更简单的方式写了
angular4.0的装饰器还包括:
Component(组件装饰器),Directive(指令装饰器),Input(输入属性装饰器),
Pipe(管道装饰器),Output(输出属性装饰器)
类型定义文件
如果要在typescript中使用第三方插件比如jquery的话.就必须引入,
这个插件的typescript解析文件;
可以用typings下载第三方插件的typescript解析文件;