• ① 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));
    
  • 相关阅读:
    【转】Flask安装
    【转】Mac OS X 中 Zsh 下 PATH 环境变量的正确设置
    【转】谁说Vim不是IDE?(二)
    【转】谁说Vim不是IDE?(三)
    【转】谁说Vim不是IDE?(一)
    【转】终极 Shell
    【转】开始使用Mac OS X——写给Mac新人
    【转】如何实现一个malloc
    《神经网络和深度学习》系列文章十六:反向传播算法代码
    Vue.js之生命周期
  • 原文地址:https://www.cnblogs.com/pleaseAnswer/p/14979638.html
Copyright © 2020-2023  润新知