一、泛型的认识

泛型可以简单理解为类型变量,它是一种特殊的变量,只用于表示类型而不是值

二、定义一个简单的泛型

  • 1、定义泛型

    function identity<T>(arg: T): T {
        return arg;
    }

    identity就叫泛型函数

  • 2、直接调用这个函数(推荐)

    console.log(identity('hello'));
    console.log(identity(20));
  • 3、指定类型的调用

    console.log(identity<string>('hello'));
    console.log(identity<number>(20));
    console.log(identity<Array<number>>([1,2,3,4]));

三、Symbol的使用

传统的javascript中数据类型有七种string,number,boolean,null,undefined,object,及ES6中的Symbol,数组属于object,函数属于object数据类型

  • 1、Symbol表示唯一的,创建一个Symbol必须创建对象的方式创建

    let sym1 = Symbol();
    let sym2 = Symbol('key'); //可以不写key
    let sym3 = Symbol('key');
  • 2、两个Symbol进行比较是false

    console.log(sym2== sym3); //false
  • 3、如果用Symbol表示对象的key只能用[]访问

    let obj1 = {
        [sym1]:'hello word',
        name:'zhansan'
    };
    console.log(obj1['name']);
    console.log(obj1[sym1]);
  • 4、可以用Symbol来做类里面的函数名称

    class C1{
        [sym1](){
            return 'C1'
        }
    }
    let c1 = new C1();
    console.log(c1[sym1]());
  • 5、使用Symbol.for()创建两个相同的Symbol

    let sym4 = Symbol.for('key1');
    let sym5 = Symbol.for('key1');
    console.log(`sys4是否等于sym5:${sym4==sym5}`);
  • 6、Symbol.keyFor(xx)获取一个Sysmbolkey

    console.log(`${Symbol.keyFor(sym4)}`); //结果是key1  
  • 7、match的使用

    对象的Symbol.match属性,指向一个函数。当执行str.match(myObject)时

    class MyMatcher {
        [Symbol.match](string) {
            return 'hello world'.indexOf(string);
        }
        foo(string){
            return 'hello world'.indexOf(string);
        }
    }
    console.log('h'.match(new MyMatcher())) // 0
    console.log((new MyMatcher()).foo('h')) // 0
  • 8、更多关于Symbol的请查阅ES6中Symbol

四、关于迭代中的for...offor...in的区别

  • 1、for..in迭代的是对象的键的列表
  • 2、for..on迭代的出来的是值
  • 3、ES3或者ES5中使用for..of会报错

五、模块的认识

传统的javascript开发过程中要使用模块化开发一般使用seajsRequire.js类的处理,模块在其自身的作用域里执行,而不是在全局作用域里,这意味着定义在一个模块里的变量,函数,类等等在模块外部是不可见的。

  • 1、两个模块之间的关系是通过在文件级别上使用importsexports建立的
  • 2、任何声明(比如变量,函数,类,类型别名或接口)都能够通过添加export关键字来导出

    // 导出一个变量
    export const numberRegexp = /^\d+$/;
    
    //导出一个接口
    export interface StringValidator {
        isAcceptable(s: string): boolean;
    }
    
    // 导出一个类
    export class Person {
        name: string;
        age: number;
    
        constructor(name: string, age: number) {
            this.name = name;
            this.age = age;
        }
    
        say(): string {
            return `我的名字叫:${this.name}--,我今年:${this.age}`;
        }
    }
    
    // 导出一个函数
    export const foo = function foo(...arg): number {
        return arg.reduce((pre, next) => {
            return (pre + next)
        })
    }
    
    // 默认导出,一个文件只能有一个默认导出
    export default class Animal {
        private name: string;
        private color: string;
    
        constructor(name: string, color: string) {
            this.name = name;
            this.color = color;
        }
    
        cay():string{
            return `${this.color}的${this.name}在叫`;
        }
    }
  • 3、别的文件引入这个文件

    import Animal,{numberRegexp, StringValidator, Person, foo} from '文件路径';
    
    console.log(numberRegexp.test('123'));
    console.log(foo(1,2,3,4));
    
    let person = new Person('李四',20);
    console.log(person.say());
    
    let dog = new Animal('大黄狗','黄色');
    console.log(dog.cay());
  • 4、导入的时候定义别名,避免名字一样的冲突

    import Animal,{numberRegexp as numReg, StringValidator, Person, foo} from '文件路径';

六、使用命名空间namespace,

传统的javascript开发中一般定义一个对象,或者即使函数,typescript解决了这个问题,在命名空间里面的东西,需要对外暴漏的就使用export,不需要的就不暴漏出去

  • 1、定义的格式

    // 在命名空间里面定义一系列的验证器  
    namespace Validation {
        //定义一个数字的验证器
        export const numberRegexp = /^[0-9]+$/;
        //定义一个字母的验证器
        export const lettersRegexp = /^[A-Za-z]+$/;
    }
  • 2、使用

    // 使用 
    console.log(Validation.numberRegexp.test('123'));
    console.log(Validation.lettersRegexp.test('123'));
  • 3、命名空间分文件的使用

    • 1、定义一个接口的命名空间

      ***Validation.ts文件***
      namespace Validation {
          export interface StringValidator {
              isAcceptable(s: string): boolean;
          }
      }
    • 2、定义一个实现上面这个命名空间的接口文件

      ***LettersOnlyValidator.ts文件***
      //下面三个正斜杠表示引入别的文件
      /// <reference path="Validation.ts" />
      namespace Validation {
          const lettersRegexp = /^[A-Za-z]+$/;
          export class LettersOnlyValidator implements StringValidator {
              isAcceptable(s: string) {
                  return lettersRegexp.test(s);
              }
          }
      }
      
      let letter = new Validation.LettersOnlyValidator();
      console.log(letter.isAcceptable('asdA'));
  • 4、模块与命名空间结合起来

    • 1、定义一个带命名空间的模块

      ***Validation.ts文件***
      export namespace Validation1{
          export const numberRegexp = /^[0-9]+$/;
      }
    • 2、使用

      import * as test from './Validation';
      console.log(test.Validation1.numberRegexp.test('123'));