typescript

typeScript简介

  1. javaScript的超集
  2. 遵循ES6
  3. 兼容ES5
  4. typeScript线上编译器: http://www.typescriptlang.org/play/index.html
  5. typeScript本地编译器: npm install -g typescript ; tsc -version 可以查看是否安装成功
  6. 编译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是一个数组;
["我的名字是是", "年龄是是"", "还有别的"]

变量

指定变量类型

  1. 声明变量
    在声明变量时,可以为变量添加类型.比如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;
  1. 函数中声明返回值和参数
function test(name: tring) :string{
    return "123";
}

括号里面的是声明函数的参数类型,括号后面的是声明返回值的类型;
如果是没有返回值就用 :void

function a(age: number) :void{
    console.log(a)
}
  1. 自定义类型
    变量声明的类型可以是自定义的类(也就是构造函数)
class Person {
    name: string;
    age: number;
}
var zhangsan :Person = new Person();
  1. 推测类型
    在typeScript环境中,如果变量的声明没有声明类型也没有any.那么typescript会根据
    变量的第一个值.来推测变量的数据类型;
var a="lifei"   //typescript默认a的类型是string;

变量默认值;

  1. 普通的变量默认值
let name: string = "lifei";
  1. 函数的变量默认值
    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操作符是三个点: "...",代表任意数量的参数;

  1. 在声明函数中使用
    如果在声明函数中作为默认参数,则代表任意数量的参数数组
function func1(...args) {
    args.forEach(function(arg){
        console.log(arg)
    })
}
func1(1, 2, 3);
func1(8, 9, 10, 11, 12);
  1. 在调用函数中使用
    在调用函数中使用,后面跟一个数组.代表把数组里的元素当做函数的参数挨个传入
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函数

控制函数的执行过程,手动的暂停或恢复代码的执行.类似于打断点的行为;

  1. 声明generator函数,在function后面加星号"*";function* doSometing(){}
  2. 打断点,在需要暂停的位置加上yield,类似于return;暂时停止;可以跟返回值;
  3. 函数运行并不会执行函数里的代码,而是返回一个运行对象,var a= doSometing();
    执行这个对象的next方法,才会运行函数,到断点,再次运行到下一个断点;a.next();;
  4. 返回值var d = a.next().value;;
  5. 这是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() => {}
  1. 箭头函数最常用的地方是匿名函数,比如setTimeout,filter,setInterval的回调函数
setTimeout((a, b) => {
    console.log(a);
    console.log(b);
}, 1000)
  1. 箭头函数的匿名函数有一些简写操作
    比如:单行匿名函数
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(受保护)

  1. public声明的属性可以在类的外面,实例化之后由实例调用.类的属性默认是public;
  2. private声明的属性只能再类里面用this调用(比如this.name).不能在类的外面用实例调用;
  3. protected声明的属性不能在外面调用,但是可以在子类里面调用;

构造函数constructor

  1. 在构造函数里的代码只会在实例化的时候执行一次;
  2. 构造函数只是一个实例化的时候向类里面传递参数的入口.
  3. 构造函数的参数并不会成为类的属性,除非给参数添加访问控制符.
    说白了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属性;

类的继承

  1. 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的实例;
  1. 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)

接口用来简历某种代码约定,使得其他开发者在调用某个方法或者
创建新的类时必须遵循接口所定义的代码约定;
简单来说就是定义接口的时候,规定了一定的属性,方法;
一个类使用这个接口,那么这个类就要也有这些属性和方法;

  1. 定义一个接口
interface IPerson {
    name: string;
    age: number;
}
  1. 作为函数的参数的接口使用
class Person {
    constructor(public config: IPerson){}
}
var p1 = new Person({name: "lifei", age: 13});
//因为类Person的构造函数的参数使用了接口IPerson,在用new 创建Person实例的时候,
//构造函数的参数就必须有name,age属性;
  1. 作为类的接口使用
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解析文件;

原文地址:https://www.cnblogs.com/bridge7839/p/7470483.html