zoukankan      html  css  js  c++  java
  • ① ts基础

    前言

    • npm i -g typescript
    • $tsc -v
    tsc test.ts // 编译
    node test.js // 执行
    
    const hello: string = 'Hello World!'
    console.log(hello)
    

    1 对象+基本类型

    1.1 ts是一种面向对象的编程语言

    • 面向对象有两个概念: 对象 + 类

      • 类:一个模板,描述一类对象的行为和状态

      • 对象: 类的一个实例

    class Site {
        name(): void {
            console.log('yaoyao')
        }
    }
    var obj = new Site();
    obj.name();
    

    1.2 ts的基础类型

    ts的基础类型 描述
    any 任意类型
    number 数字
    string 字符
    boolean 布尔
    enum 枚举
    void 用于标识方法返回值的类型,表示该方法没有返回值
    null 表示对象值缺失
    undefined 用于初始化变量为一个未定义的值
    never 其他类型的子类型,代表从不会出现的值
    1.2.1 any
    • any是ts针对编程时类型不明确的变量使用的一种数据类型
    • 变量的值会动态改变时
    • 任意值类型可以让这些变量跳过编译阶段的类型检查
    let x: any = 1; // 数字类型
    x = 'i am who i am'; // 字符串类型
    x = false; // 布尔类型
    
    let x: any = 4;
    x.ifExists(); // 正确,这里不会检查ifExists方法是否存在
    x.toFixed(); // 正确
    
    let arrayList: any[] = [1, false, 'fine'];
    
    1.2.2 空校验(strictNullChecks)特性
    • 在ts中启用严格的空校验(strictNullChecks)特性,可以使得null undefined只能被赋值给void或本身对应的类型
    let x: number;
    x = 1; // 运行正确
    x = undefined; // 运行错误
    x = null; // 运行错误
    
    let x: number | null | undefined;
    x = 1; // 运行正确
    x = undefined; // 运行正确
    x = null; // 运行正确
    
    1.2.3 never
    • never 是其他类型的子类型,代表不会出现的值
    • 声明为never类型的变量只能被never类型所赋值
    • 在函数中通常表现为抛出异常或无法执行到终止点(无限循环)
    let x: never;
    let y: number;
    
    x = 123; // 运行错误
    x = (() => { throw new Error('exception') })(); // 运行正确
    // 运行正确 never类型可以赋值给数字类型
    y = (() => { throw new Error('exception') })(); 
    
    function error(message: string): never {
        throw new Error(message);
    }
    
    function loop(): never {
        while(true) {}
    }
    

    2 ts函数

    /**
     * 函数定义 函数返回值
     * 1 return_type是返回值的类型
     * 2 返回值的类型需要与函数定义的返回类型(return_type)一致
     * */ 
    // function function_name() [:return_type] {
    //     // 执行代码
    //     [return value;]
    // }
    function greet(): string {
        return 'hello world';
    }
    function caller() {
        var msg = greet();
        console.log(msg)
    }
    caller()
    

    2.1 带参函数

    /**
     * 带参数函数
     * param1、param2 为参数名
     * datatype为参数类型
    */
    // function func_name(param1[: datatype], param2[: datatype]) {
    // }
    function add(x: number, y: number): number {
        return x + y;
    }
    console.log(add(1, 2));
    

    2.2 可选参数

    • 在ts函数里,如果我们定义了参数,则必须传入这些参数
    • 除非将这些参数设置为可选,可选参数使用问号标识?
    • 可选参数必须跟在必需参数后面
    function buildName(firstName: string, lastName: string) {
        return firstName + ' ' + lastName;
    }
    let result1 = buildName('Bob'); // 错误
    let result2 = buildName('Bob', 'Adams', 'sr.'); // 错误
    let result3 = buildName('Bob', 'Adams'); // 正确
    
    function buildName2(firstName: string, lastName?: string) {
        return firstName + ' ' + lastName;
    }
    let result1 = buildName('Bob'); // 正确
    let result2 = buildName('Bob', 'Adams', 'sr.'); // 错误
    let result3 = buildName('Bob', 'Adams'); // 正确
    

    2.3 默认参数

    • 参数不能同时设置为可选和默认
    // function function_name(param1[: type], param2[: type] = default_value) {
    // }
    
    function calculate_discount(price: number, rate: number = 0.50) {
        var discount = price * rate;
        console.log('计算结果:', discount);
    }
    calculate_discount(1000);
    calculate_discount(1000, 0.30);
    

    2.4 剩余参数

    • 允许我们将一个不确定数量的参数作为一个数组传入
    • 函数的最后一个命名参数restOfName以...为前缀,它将成为一个由剩余参数组成的数组,索引值从0到resOfName.length
    function buildName(firstName: string, ...resOfName: string[]) {
        return firstName + ' ' + resOfName.join('');
    }
    let employeeName = buildName('Joseph', 'Same', 'Lucas', 'Andy');
    
    function addNumbers(...nums: number[]) {
        var i;
        var sum: number = 0;
        for(i = 0; i < addNumbers.length; i++) {
            sum = sum + nums[i];
        }
        console.log('和为:', sum)
    }
    addNumbers(1, 2, 3)
    addNumbers(10, 10, 11, 111, 1111)
    

    2.5 匿名函数

    • 在程序运行时动态声明,除了没有函数名外,其他的与标准函数一样
    // var res = function([arguments]) { ... }
    
    var msg = function() {
        return 'hello world';
    }
    console.log(msg())
    
    var res = function(a: number, b: number) {
        return a * b;
    };
    console.log(res(12, 2))
    
    ##### 匿名函数自调用
    
    ```ts
    (function() {
        var x = 'hello';
        console.log(x)
    })()
    

    2.6 构造函数

    /**
     * 构造函数
     * arg1,arg2,...argN: 参数列表
     * functionBody: 一个含有包括函数定义的js语句的字符串
    */
    // var res = new Function([arg1[, arg2[, ...argN]],] functionBody)
    
    var myFunction = new Function('a', 'b', 'return a * b');
    var x = myFunction(4, 3);
    console.log(x);
    

    2.7 递归函数

    • 在函数内调用函数本身
    function factorial(number) {
        if(number <= 0) {
            return 1;
        } else {
            return (number * factorial(number - 1))
        }
    }
    console.log(factorial(6));
    

    2.8 Lambda函数,即箭头函数

    // ([param1, param2, ...param n]) => statement;
    // ([param1, param2, ...param n]) => { // 代码块 }
    var foo = (x: number) => 10 + x;
    console.log(foo(100));
    
    var foo2 = (x: number) => {
        x = 10 + x;
        console.log(x);
    }
    foo2(100);
    
    var func = x => {
        if(typeof x == 'number') {
            console.log(x + '是一个数字');
        } else if(typeof x == 'string') {
            console.log(x + '是一个字符串');
        }
    }
    func(12);
    func('Tom');
    
    var disp = () => {
        console.log('Function invoked');
    }
    disp();
    

    2.9 函数重载

    • 重载是方法名相同,而参数不同,返回类型可以相同也可以不同
    • 每个重载的方法都必须有一个独一无二的参数类型列表
    • 参数类型不同,则参数类型应设置为any
    • 参数数量不同,可以将不同的参数设置为可选
    2.9.1 参数类型不同
    • function disp(string): void;
    • function disp(number): void;
    2.9.2 参数数量不同
    • function disp(n1: number): void;
    • function disp(x: number, y: number): void;
    2.9.3 参数类型顺序不同
    • function disp(n1: number, s1: string): void;
    • function disp(s: string, n: number): void;
    function disp2(s1: string): void;
    function disp2(n1: number,s1: string): void;
    function disp2(x: any, y?: any): void {
        console.log(x);
        console.log(y);
    }
    disp2('abc');
    disp2(1, 'xyz');
    

    3 元组

    • 数组中元素类型一般是相同的,如果存储的元素类型不同,则需要使用元组

    • 元组中允许存储不同类型的元素,元组可以作为参数传递给函数

    • 语法:var tuple_name = [value1, value2, value3, ...value n]

    var mytuple = [10, 'yaoyao'];
    
    var mytuple1 = [];
    mytuple1[0] = 120;
    mytuple1[1] = 220;
    

    3.1 访问元组

    var mytuple2 = [10, 'yaoyao'];
    console.log(mytuple2[0]);
    

    3.2 解构元组

    var a = [10, 'yaoyao'];
    var [b, c] = a;
    console.log(b);
    console.log(c);
    

    4 联合类型

    • 联合类型可通过管道(|)将变量设置多种类型,赋值时可以根据设置的类型来赋值

    注意:只能赋值指定类型,否则报错

    • 语法: Type1|Type2|Type3
    var val: string | number;
    val = 12;
    console.log('数字为:' + val);
    val = 'yaoyao';
    console.log('字符串为:' + val);
    // var val:string|number;
    // val = true; // 报错
    

    4.1 将联合类型作为函数参数使用

    function disp(name: string | string[]) {
        if(typeof name == 'string') {
            console.log(name);
        } else {
            var i;
            for(i = 0; i < name.length; i++) {
                console.log(name[i]);
            }
        }
    }
    disp('yaoyao');
    console.log('输出数组...');
    disp(['hello', 'yaoyao', 'are', 'you', 'ok'])
    

    4.2 联合类型数组

    var arr: number[] | string[];
    var i: number;
    arr = [1, 2, 4];
    console.log('**数字数组**');
    for(i = 0; i<arr.length; i++) {
        console.log(arr[i]);
    }
    arr = ['yaoyao', 'hello', 'world'];
    console.log('**字符串数组**');
    for(i = 0; i<arr.length; i++) {
        console.log(arr[i]);
    }
    

    5 接口interface

    • 接口是一系列抽象方法的声明,是一些方法特征的集合,这些方法都应该是抽象的,需要具体类去实现,三方可通过这组抽象方法调用,让具体的类执行具体的方法

    接口不能转换为js,它只是ts的一部分

    • 定义:interface interface_name {}
    interface IPerson {
        firstName: string,
        lastName: string,
        sayHi: ()=> string
    }
    var customer: IPerson = {
        firstName: 'Tom',
        lastName: 'Hanks',
        sayHi: (): string => 'Hi there'
    }
    
    console.log('Customer 对象 ');
    console.log(customer.firstName);
    console.log(customer.lastName);
    console.log(customer.sayHi());
    
    var employee: IPerson = {
        firstName: 'Zhou',
        lastName: 'yaoyao',
        sayHi: (): string => 'Hello!!'
    }
    
    console.log('Employee 对象 ');
    console.log(employee.firstName);
    console.log(employee.lastName);
    console.log(employee.sayHi());
    

    6 对象

    • 对象是包含一组键值对的实例。值可以是标量、函数、数组、对象等
    var obj_name = {
        key1: 'value1', // 标量
        key2: 'value',
        key3: function() {},
        key4: ['content1','content2']
    }
    
    var sites1 = {
        site1: 'zhou',
        site2: 'yaoyao'
    }
    console.log(sites1.site1);
    console.log(sites1.site2);
    

    6.1 类型模板

    var sites2 = {
        site1: 'zhou',
        site2: 'yaoyao',
        sayHello: function() {} // 类型模板
    }
    sites2.sayHello = function() {
        console.log('hello' + sites2.site2);
    }
    sites2.sayHello()
    

    6.2 对象也可以作为一个参数传递给函数

    var sites3 = {
        site1: 'zhou',
        site2: 'yaoyao'
    }
    var invokesites = function(obj: {site1: string, site2: string}) {
        console.log('site1:'+obj.site1);
        console.log('site2:'+obj.site2);
    }
    invokesites(sites3)
    

    6.3 鸭子类型

    • 关注点在于对象的行为,能做什么;而不是关注对象所属的类型

    • 鸭子类型是动态类型的一种风格,是多态的一种形式

    • 在这种风格中,一个对象有效的语义,不是由继承自特定的类或实现特定的接口,而是由“当前方法和属性的集合”决定

    • 多态就是允许方法重名 参数或返回值可以是父类型传入或返回。

    interface IPoint {
        x: number
        y: number
    }
    function addPoints(p1: IPoint, p2: IPoint): IPoint {
        var x = p1.x + p2.x
        var y = p1.y + p2.y
        return {x, y}
    }
    var newPoint = addPoints({x:3, y:4},{x:5, y:1})
    console.log('newPoint', newPoint);
    
    // var newPoint2 = addPoints({x:3},{x:5, y:1}) // 错误
    

    7 类

    • ts是面向对象的js

    • 类描述了所创建的对象共同的属性和方法

    • ts支持面向对象的所有特性

    • 定义: calss class_name { // 类作用域 }

    • 类可以包含以下几个模块(类的数据成员):

    • 001 字段--字段是类里面声明的变量。字段表示对象的有关数据

    • 002 构造函数--类实例化时调用,可以为类的对象分配内存

    • 003 方法--方法为对象要执行的操作

    7.1 创建类的数据

    • this关键字表示当前类实例化的对象
    • 构造函数的参数名与字段名相同
    class Car {
        // 字段
        engine: string;
        // 构造函数
        constructor(engine: string) {
            this.engine = engine
        }
        // 方法
        disp(): void {
            console.log('发动机为:' + this.engine);
        }
    }
    

    7.2 创建实例化对象

    • var object_name = new class_name([arguments])
    • 类中的字段属性和方法可以使用.来访问
    • obj.field_name
    • obj.function_name()
    var obj = new Car('Engine 1')
    
    class Car2 {
        engine: string;
        constructor(engine: string) {
            this.engine = engine
        }
        disp(): void {
            console.log('函数中显示发动机型号:' + this.engine);
        }
    }
    
    var obj = new Car('xxxsy1');
    console.log('读取发动机型号:' + obj.engine);
    
    obj.disp()
    

    7.3 类的继承extends

    • 子类除了不能继承父类的私有成员(方法和属性)和构造函数,其他都可以继承
    • ts一次只能继承一个类,不支持继承多个类;但ts支持多重继承(A继承B,B继承C)
    • 语法:class child_class_name extends parent_class_name
    class Shape {
        Area: number 
        constructor(a: number) {
            this.Area = a
        }
    }
    class Circle extends Shape {
        disp(): void {
            console.log('圆的面积:' + this.Area);
            
        }
    }
    var obj11 = new Circle(233);
    obj11.disp();
    
    class Root {
        str: string;
    }
    class Child extends Root {}
    class Leaf extends Child {}
    
    var obj22 = new Leaf()
    obj22.str = 'Hello'
    console.log(obj22.str);
    

    7.4 继承类的方法重写

    • supper关键字是对父类的直接引用,该关键字可以引用父类的属性和方法
    class PrinterClass {
        doPrint(): void {
            console.log('父类的doPrint()方法');
        }
    }
    class StringPrinter extends PrinterClass {
        doPrint(): void {
            super.doPrint()
            console.log('子类的dePrint()方法');
        }
    }
    
    #### 7.5 static关键字
    
    * 用于定义类的数据成员(属性和方法)为静态,静态成员可以直接通过类名调用
    
    ```ts
    class StaticMen {
        static num: number;
        static disp(): void {
            console.log('num值为:' + StaticMen.num);
        }
    }
    StaticMen.num = 12
    StaticMen.disp() // num值为12
    

    7.6 instanceof运算符

    • 用于判断对象是否是指定的类型,如果是返回true,否则返回false
    class PersonI {}
    var objI = new PersonI()
    var isPersonI = objI instanceof PersonI;
    console.log('objI对象是PersonI类实例化来的吗?' + isPersonI);
    

    7.7 访问控制修饰符

    • ts中可使用访问控制符来保护类、对象、方法和构造方法的访问

    • ts支持3种不同的访问权限:

    • 001 public(默认) 公有,可以在任何地方被访问

    • 002 protected 受保护,可以被其自身以及其子类和父类访问

    • 003 private 私有,只能被其定义所在的类访问

    class Encapsulate {
        str1: string = 'Hello';
        private str2: string = 'world';
    }
    var objII = new Encapsulate()
    console.log(objII.str1);
    // console.log(objII.str2);
    

    7.8 类和接口

    • 类可以实现接口,使用关键字implements
    interface ILoan {
        interest: number
    }
    class AgriLoan implements ILoan {
        interest: number
        rebate: number
        constructor(interest: number, rebate: number) {
            this.interest = interest
            this.rebate = rebate
        }
    }
    var objIl = new AgriLoan(10, 1)
    console.log('利润为:' + objIl.interest + ',抽成为:' + objIl.rebate);
    

    8 命名空间

    • 关键字 namespace
    • 目的:解决重名问题
    • 命名空间定义了标识符的可见范围,一个标识符可在多个名字空间中定义,且在不同名字空间中的含义是互不相干的
    • 在外部调用命名空间中的类和接口,需要在类和接口添加extends关键字
    • 如果一个命名空间在一个单独的ts文件中,则应使用三斜杠///应用它
      • /// <reference path = 'SomeFileName.ts' />
    // IShape.ts文件
    namespace Drawing {
        export interface IShape {
            draw()
        }
    }
    // Circle.ts文件
    /// <reference path = 'IShape.ts'/>
    namespace Drawing {
        export class Circle implements IShape {
            public draw() {
                console.log('Circle is drawn');
            }
        }
    }
    // Triangle.ts文件
    /// <reference path = 'IShape.ts'/>
    namespace Drawing {
        export class Triangle implements IShape {
            public draw() {
                console.log('Triangle is drawn'); 
            }
        }
    }
    // TestShape.ts文件
    /// <reference path = 'IShape.ts'/>
    /// <reference path = 'Circle.ts'/>
    /// <reference path = 'Triangle.ts'/>
    function drawAllShapes(shape: Drawing.IShape) {
        shape.draw()
    }
    drawAllShapes(new Drawing.Circle())
    drawAllShapes(new Drawing.Triangle())
    
    // tsc --out nameSpaceTest.js TestShape.ts
    // node nameSpaceTest.js
    

    8.1 嵌套命名空间

    namespace namespace_name1 {
       export namespace namespace_name2 {
         export class class_name {}
       }
    }
    
    • 成员的访问使用点好.来实现
    // Invoice.ts文件
    namespace Runoob {
        export namespace invoiceApp {
            export class Invoice {
                public calculateDiscount(price: number) {
                    return price * 4
                }
            }
        }
    }
    // IvoiceTest.ts文件
    /// <reference path = 'Invoice.ts'/>
    var invoice = new Runoob.invoiceApp.Invoice()
    console.log(invoice.calculateDiscount(500));
    

    9 声明文件

    9.1 栗子

    • js中 使用jQuery
      • $('#foo);
      • jQuery('#foo')
    • ts中
      • jQuery('#foo') // index.ts(1,1): err: Cannot find name 'jQuery'
      • 使用declare关键字来定义它的类型,帮助ts判断我们传入的参数类型
      • declare var jQuery: (selector: string) => any;
      • jQuery('#foo')

    declare定义的类型只会用于编译时的检查,编译结果会被删除

    9.2 声明文件

    • 声明文件以.d.ts为后缀
    • 声明文件不包含实现,只是类型声明
    • 声明文件或模板的语法格式: declare module Module_Name {}
    • ts引入声明文件语法格式: ///
    // CalcThirdPartyJsLib.js文件
    var Yaoyao;
    (function(Yaoyao) {
        var Calc = (function() {
            function Calc() {}
        })
        Calc.prototype.doSum = function(limit) {
            var sum = 0;
            for(var i=0; i<=limit; i++) {
                sum = sum + i
            }
            return sum;
        }
        Yaoyao.Calc = Calc;
        return Calc;
    })(Yaoyao || (Yaoyao = {}))
    var test = new Yaoyao.Calc()
    
    //Calc.d.ts文件
    declare module Yaoyao {
        export class Calc {
            doSum(limit: number): number
        }
    }
    // 把声明文件加入到ts中
    // CalcTest.ts文件
    /// <reference path = 'Calc.d.ts'/>
    var obj = new Yaoyao.Calc()
    console.log(obj.doSum(10));
    
  • 相关阅读:
    Roce ofed 环境搭建与测试
    Ubuntu 1804 搭建NFS服务器
    Redhat 8.0.0 安装与网络配置
    Centos 8.1 安装与网络配置
    SUSE 15.1 系统安装
    VSpare ESXi 7.0 基本使用(模板、iso、SRIOV)
    VSpare ESXi 7.0 服务器安装
    open SUSE leap 15.1 安装图解
    KVM虚拟机网卡连接网桥
    GitHub Action一键部署配置,值得拥有
  • 原文地址:https://www.cnblogs.com/pleaseAnswer/p/14979638.html
Copyright © 2011-2022 走看看