美文网首页
TypeScript

TypeScript

作者: 洛珎 | 来源:发表于2020-11-12 16:53 被阅读0次

    1.TS概述

    1.1 TS相比于js的优势:

    优势一:类型化思维方式,提前发现错误,减少改bug时间;
    优势二:提高代码可读性,并使维护和重构代码根据容易;
    优势三:补充了接口,枚举等开发大型应用时js缺失的功能;

    1.2.开发工具准备
    1.2.1 安装解析ts工具包tsc(将ts转化成js)
    image.png
    安装: npm i -g typescript
    1.3第一个ts文件
    1.3.1执行代码,分两步:

    1)ts -> js代码:tsc 文件名.ts

    1. 执行js:node 文件名.js;

    解释:
    ts转化js命令(tsc 文件名.ts):
    新建tsdemo文件夹,新建hello.ts文件,在该文件目录下打开终端,输入tsc hello.ts,此时,文件夹就多出一个hello.js,即可生成同名的js代码

    执行js命令(node 文件名.js):

    image.png
    1.3.2简化执行ts步骤

    问题:每次修改代码后,都需要重复执行tsc 文件名.tsnode 文件名.js命令,太繁琐。
    简化方式:使用ts-node包,直接在node.js中执行js代码(ts-node包内部已将ts->js),然后执行js代码

    安装命令: npm i -g ts-node
    执行命令:ts-node 文件名.ts

    image.png

    2 变量

    2.1 什么是变量

    两步:1.声明变量并指定类型 2.给变量赋值
    如:第一步:let age: number = 18

    2.2 ts中的数据类型

    ts为了编码规范,增加了类型校验,提供以下数据类型:
    布尔类型(boolearn);
    数字类型(number);
    字符串类型(string);
    数组类型(array);
    元组类型(tuple);
    枚举类型(enum);
    任意类型(any);
    null和undefined;
    void类型;
    never类型
    1).布尔类型

    var flag:boolean = true;
    flag = false;
    console.log('flag:', flag); // false
    

    2).数字类型

    var num:number =123;
    num = 234;
    console.log('num:', num); // 234
    

    3).string类型

    var str:string ='hello';
    str = 'hi';
    console.log('str:', str); // hi
    

    4).数组类型

    // 三种方式
    // 第一种:
    var arr1:number[] = [11,111,111];
    console.log(arr1); // [11,111,111]
    
    // 第二种:
    var arr2:Array<number> = [11,22,33];
    console.log(arr2); // [11,22,33]
    
    //第三种:
    var arr0:any[] = ['233433', 33, true];
    console.log(arr0); // ['233433', 33, true]
    

    5).元组类型(tuple):属于数组的一种,每一个位置指定一中类型

    /**
     */
    let arr3:[number,string] =[123, 'good'];
    console.log('arr3:',arr3);
    

    6).枚举类型:在状态程序中用自然语言中相应含义的单词来代表某一状态
    enum 枚举名 {
    标识符[=整数常数],
    标识符[=整数常数],
    ...
    标识符[=整数常数]
    }

    //如果标识符没有赋值,它的值就是下标
    enum Color {red,green=4, 'orange'};
    let thisColor_red:Color = Color.red;
    let thisColor_green :Color=Color.green;
    let thisColor_orange :Color=Color.orange;
    // 如果标识符没有赋值,它的值就是下标
    console.log(thisColor_red); // 0
    // 赋值
    console.log('thisColor_green:', thisColor_green); // 4
    // 改变下标
    console.log('thisColor_orange:', thisColor_orange); // 5
    

    7).任意类型(any)

    var num9: any = 123;
    num9= 'str';
    num9 = true;
    console.log('num9:', num9); // true
    
    //使用Object会报错,ts没有Object类型,可使用any
    // var oBox:any =document.getElementById('box');
    // oBox.style.color = 'red';
    

    8).null 和 undefined其它类型的子类型

    //可能是undefined,错误写法
    var num11:number;
    console.log(num11); //声明未赋值,会报错 输出:undefined
    
    //可能是undefined,正确写法
    var num12:undefined;
    console.log(num12); //输出:undefined
    
    //可能是null时
    var num13 :null;
    num13 = null;
    console.log(num13); // null
    
    //可能是null,可能是undefined时
    var num15:number | null | undefined;
    num15 = 1234;
    console.log(num15); // 1234
    

    9).void类型:表示方法没有返回任何类型

    // 错误写法
    // function run(): undefined {
    //     console.log('run');
    // }
    // run();
    
    //正确写法
    function running(): void {
        console.log('123');  // 123
    }
    running();
    

    10). never类型:是其他类型(包括null和undefined)的子类型,代表从不会出现的值
    这意味着声明never的变量只能被never类型所赋值

    // var a:never;
    // a = (()=>{
    //     throw new Error('错误');
    // })();
    

    3.函数

    1).以前es5:函数声明

    // 函数的定义
        function run() {
            return 'run1';
        }
    
        // 匿名函数
        var run2 = function() {
            return 'run2'
        }
    

    2).ts函数声明

        function runTs():string {
            return 'run1';
        }
        // 匿名函数
        var run2Ts = function():string {
            return 'run2ts'
        }
        //函数调用
        run2Ts() //run2ts
    
    

    3).ts中定义方法传参

    function getInfo(name:string , age:number):string {
        return `${name}----${age}`;
    }
    getInfo('sum',11); // sum====11
    
    var getInfoTs = function(name:string,age:number):string{
        return `${name}-${age}`;
    }
    getInfoTs('xiaozhang', 12); //xiaozhang 12
    

    4).没有返回值

    function run1():void {
        console.log('run');
    }
    run1(); //run
    

    5).方法可选参数时,加 ?
    es5里面方法的实参和形参可以不一样,但还是ts中必须一样,如果不一样就需要配置

    function getInfoTss(name:string, age?:number) {
        return `${name}----${age}`;
    }
    getInfoTss('sum');// sum
    // 注意:可选参数必须配置到参数的的后面
    

    6).默认参数
    es5里面没法设置默认参数,es6和ts都可以设置默认参数

    function getA(name:string, age:number=20):string{
        if(age){
            return `${name}--${age}`;
        }else{
            return '${name}--haha';
        }
    }
    alert(getA('张三')); // 张三--20
    alert(getA('李',30)) // 李--30
    

    7).剩余参数 三点运算符

    function sum1(a:number,b:number,...result:number[]):number{
        var sum = a + b;
        for(var i = 0; i < result.length;i++){
            sum+=result[i];
        }
        return sum;
    }
    console.log(sum1(1,2,3,4,5));//15
    // 或者
    function sum2(...result:number[]):number{
        var sum = 0;
        for(var i = 0; i < result.length;i++){
            sum += result[i];
        }
        return sum;
    }
    console.log(sum2(1,2,3,4,5,6)); //21
    

    8).函数重载:
    java中:重载指的是两个或者两个以上同名函数,但它们的参数不一样,这时会出现函数重载的情况
    ts中的重载:通过为同一个函数提供多个函数类型定义来实现多重功能的目的
    ts为了兼容ES5以及es6重载的写法和java中有区别

    function getReFn(name:string):string;
    function getReFn(name:string,age:number):string;
    function getReFn(name:string,age?:number):any{
        if(age){
            return '我叫:'+ name + '我的年龄是'+age;
        }else{
            return '我叫:'+name;
        }
    }
    
    alert(getReFn('zhangsan')); // zhangsan
    // console.log(getReFn('san', 20)); //san 20
    // console.log(getReFn(231333)); //错误写法
    

    3.类

    es5中的类

    1)最简单的类

            function Person1() {
                this.name = 'lily';
                this.age = 34;
            }
            var p = new Person1;
            console.log(p.name);
    

    2).构造函数和原型链里面增加方法

            //原型链上面的属性会被多个实例共享,构造函数不会
            function Person() {
                // 属性
                this.name = 'sam';
                this.age = 20;
                // 方法
                this.run = function () {
                    console.log(this.name + '在运动');
                }
            }
    
            //原型链
            Person.prototype.sex = "男";
            Person.prototype.work = function () {
                console.log(this.name + '工作');
            }
            var p = new Person();
            p.work(); //sam工作
    
    

    3).类的静态方法

            Person.getInfo = function () {
                console.log('静态方法');
            }
            Person.getInfo();
    

    4).构造函数

            function Person3() {
                // 属性
                this.name = 'lucy';
                this.age = 20;
                // 方法
                this.run = function () {
                    console.log(this.name + '在运动');
                }
            }
    
            Person3.prototype.sex = "女";
            Person3.prototype.work = function () {
                console.log(this.name + '逛街la');
            }
            //web类 继承Person类 原型链+对象冒充的组合继承模式
            function Web(){
    
            }
            //原型链实现继承,可以继承构造函数里面的属性和方法,也可以继承原型链上的属性和方法
            Web.prototype=new Person3();
            var w =new Web();
            w.work() //lucy逛街la
            w.run() //lucy在运动
    

    5)传参时:构造函数和原型链实例化子类的时候没法给父类传参,用call或者 Web.prototype= Person.prototype;

    function Web4(name,age){
                Person.call(this.name,age);
            }
             //或者原型链
            Web4.prototype= Person.prototype;
    
    3.2ts类

    1).类的定义

    class Person{
        name:string;
        constructor(name:string){
            this.name=name;
        }
        getName():string{
            return this.name;
        }
        setName(name:string):void{
            this.name=name;
        }
    }
    var p=new Person('sam');
    console.log(p.getName()); // sam
    p.setName('lili')
    console.log(p.getName()); //lili
    

    2).ts中实现继承

    class Animal {
        move(distanceInMeters: number = 0) {
            console.log(`Animal moved ${distanceInMeters}m.`);
        }
    }
    
    class Dog extends Animal {
        bark() {
            console.log('Woof! Woof!');
        }
    }
    
    const dog = new Dog();
    dog.bark();
    dog.move(10);
    dog.bark();
    

    3)类作为接口使用

    class Point {
        x: number;
        y: number;
    }
    
    interface Point3d extends Point {
        z: number;
    }
    
    let point3d: Point3d = {x: 1, y: 2, z: 3};
    

    4.枚举

    存在一种特殊的非计算的常量枚举成员的子集:字面量枚举成员。 字面量枚举成员是指不带有初始值的常量枚举成员,或者是值被初始化为

    任何字符串字面量(例如: "foo", "bar", "baz")
    任何数字字面量(例如: 1, 100)
    应用了一元 -符号的数字字面量(例如: -1, -100)

    enum ShapeKind {
        Circle,
        Square,
    }
    
    interface Circle {
        kind: ShapeKind.Circle;
        radius: number;
    }
    
    interface Square {
        kind: ShapeKind.Square;
        sideLength: number;
    }
    
    let c: Circle = {
        kind: ShapeKind.Square,
        //    ~~~~~~~~~~~~~~~~ Error!
        radius: 100,
    }
    

    5.类型兼容性

    函数参数双向协变
    当比较函数参数类型时,只有当源函数参数能够赋值给目标函数或者反过来时才能赋值成功。 这是不稳定的,因为调用者可能传入了一个具有更精确类型信息的函数,但是调用这个传入的函数的时候却使用了不是那么精确的类型信息。 实际上,这极少会发生错误,并且能够实现很多JavaScript里的常见模式。例如

    enum EventType { Mouse, Keyboard }
    
    interface Event { timestamp: number; }
    interface MouseEvent extends Event { x: number; y: number }
    interface KeyEvent extends Event { keyCode: number }
    
    function listenEvent(eventType: EventType, handler: (n: Event) => void) {
    }
    
    listenEvent(EventType.Mouse, (e: MouseEvent) => console.log(e.x + ',' + e.y));
    
    
    listenEvent(EventType.Mouse, (e: Event) => console.log((<MouseEvent>e).x + ',' + (<MouseEvent>e).y));
    listenEvent(EventType.Mouse, <(e: Event) => void>((e: MouseEvent) => console.log(e.x + ',' + e.y)));
    
    listenEvent(EventType.Mouse, (e: number) => console.log(e));
    

    6.迭代器和生成器

    for..of和for..in均可迭代一个列表;但是用于迭代的值却不同,for..in迭代的是对象的 键 的列表,而for..of则迭代对象的键对应的值

    let list = [4, 5, 6];
    
    for (let i in list) {
        console.log(i); // "0", "1", "2",
    }
    
    for (let i of list) {
        console.log(i); // "4", "5", "6"
    }
    

    另一个区别是for..in可以操作任何对象;它提供了查看对象属性的一种方法。 但是 for..of关注于迭代对象的值。内置对象Map和Set已经实现了Symbol.iterator方法,让我们可以访问它们保存的值。

    let pets = new Set(["Cat", "Dog", "Hamster"]);
    pets["species"] = "mammals";
    
    for (let pet in pets) {
        console.log(pet); // "species"
    }
    
    for (let pet of pets) {
        console.log(pet); // "Cat", "Dog", "Hamster"
    

    7.Symbol

    symbol类型的值是通过Symbol构造函数创建的,是不可改变且唯一的,也可以被用做对象属性的键,也可以与计算出的属性名声明相结合来声明对象的属性和类成员,

    const getClassNameSymbol = Symbol();
    
    class C {
        [getClassNameSymbol](){
           return "C";
        }
    }
    
    let c = new C();
    let className = c[getClassNameSymbol](); // "C"
    

    相关文章

      网友评论

          本文标题:TypeScript

          本文链接:https://www.haomeiwen.com/subject/otirbktx.html