目录
前言
TypeScript
简介
编译
ts基础类型
数值型
布尔值
字符串
数组
元组 Tuple
枚举
Any
Void
Undefined
Null
Never
Object
类型断言
函数声明
ts中的类
定义
继承
类的修饰符
静态属性和方法
多态
抽象类
接口
属性接口
函数接口
可索引接口
泛型
命名空间
ts事件封装
为什么要封装?
ts开发的规则
封装
首页 web前端 前端问答 一篇文章带你TypeScript入门(整理总结)

一篇文章带你TypeScript入门(整理总结)

Jan 24, 2022 pm 05:22 PM
typescript

本篇文章给大家带来了关于TypeScript入门的相关知识,希望对大家有帮助。

一篇文章带你TypeScript入门(整理总结)

前言

ts是什么?ts其实是TypeScript的一个简称,就跟JavaScript简称为js一样,官方给的解释是,ts它是js的超集,其实js的代码本质上都是ts编译的,例如写一个js代码 document.write() ,上面的提示就是ts,如图:

在这里插入图片描述
系统里面写的是ts代码,所以ts是js的超集,是给js添加拓展功能的语言,这样的语言曾经还有一个叫as,但是这个语言已经没了,它其实就是flash语言。但我么开发需要完善js的话,必须得有这样的一个东西,所以微软拿着这个as的语法开发了ts这个语言,也就是说as和ts的语法基本是一样的,只不过ts是微软开发的,然后推广的不错,现在随着我们编程越来越全民化,ts使用的也就越来越多,包括在找工作中,如果你的薪资是在12k以上的话,基本上都会问你会不会ts,现在的编程很多情况下都是用到ts,因为它能给js添加拓展功能,

比如:可以进行各种各样的模块化开发,像之前提到的AMD,CMD开发,CommonJS,es6的模块化规范。假设现在在客户端开发,有没有一种开发场景,既可以用AMD,也可以用CMD,CommonJS,es6的,

答案是没有,因为CommonJS是只能在nodejs中使用,es6的模块化开发只能在服务器中用,它们都是有各自限制的。

但是ts中,想用什么都可以,它是支持全场景的。ts它更像后端,他的语法跟java最相似,这样有什么好处?大家知道js是弱类型语言,比如一个变量先定义一个数字型,然后再重新赋值一个字符串型的,这样的话这个变量的类型就改变了,这种弱类型开发是对项目有一定的安全隐患的,

比如就用这个变量去做其他事情,它有可能变成其他类型的数据,所以对开发来说是有安全隐患的,所以必须得有ts来规范js开发,消除这个安全隐患,这就是为什么ts像java、#c这些后端语言,这些强类型语言定义变量的时候,需要先声明这些变量的类型是什么,一旦定义这个变量的类型后,后期是不允许修改类型的,有了这样的规范约束后,开发就更加安全了。

现在ts使用的场景是非常广泛:js的提示(编辑器内置了规范语法的ts),主流框架vue,react在底层写框架的时候用的也是ts。

说这么多,下面直接介绍ts,也就是TypeScript。


TypeScript

简介

ts是一个给js添加特性的扩展语言。

  1. TypeScript是由微软开发的一款开源的编程语言。
  2. TypeScript是JavaScript的超集,遵循最新的es6、es5规范。TypeScript扩展了JavaScript的语法。
  3. TypeScript更像后端java、C#这样的面向对象语言,可以让js开发大型企业项目。
  4. 谷歌也在大力支持TypeScript的推广,谷歌的angular2.x+就是基于TypeScript语法。
  5. 最新的vue、React也可以集成TypeScript。
  6. nodeJs矿建Nestjs、midway中用的就是TypeScript语法。

能给js增加的功能有

  • 类型批注和编译时类型检查
  • 类型推断
  • 类型擦除
  • 接口
  • 枚举
  • Mixin
  • 泛型编程
  • 名字空间
  • 元组
  • Await
  • 模块
  • lambda 函数的箭头语法
  • 可选参数以及默认参数

js 是一个弱类型的语言,但ts是强类型的,语法很相像,但ts算是扩展的js的语法,ts通过类型注解,提供编译js时的静态类型检查。


编译

ts无法直接运行,所以只能编译成js运行。类似sass用来编译css,不能直接运行。
编译工具 - typescript

在全局任意位置下,先检测是否安装过ts

tsc --version
登录后复制

在这里插入图片描述

npm install -g typescript
登录后复制

在这里插入图片描述

检测是否安装成功:

tsc -v
登录后复制

ts文件的后缀是ts,编译命令:

tsc 被编译的文件
登录后复制

会在被编译文件的同级目录下生成一个同名的js文件。

生成自定义名称路径的文件:

tsc 被编译的文件 --outFile 编译后的文件路径
登录后复制

初始化命令:

tsc --init
登录后复制

执行初始化命令后,会生成一个tsconfig.json文件,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AJUcQvUG-1623422064118)(media/1623161483290.png)]

其中常用配置项说明:

代表ts要转换后js版本

"target": "es5"
登录后复制

如果ts是以模块形式书写的,使用什么样的模块化规范,默认是commonJS

"module": "amd"
登录后复制

配置输出目录,可自己设置

"outDir": "./"
登录后复制

在这里插入图片描述

上面的配置项配置好以后,执行监视命令会自动编译:

tsc -w
登录后复制

使用amd规范的时候,需要将require.js文件拷贝到项目根目录下,且需要一个出口文件:

<script src="require.js" data-main="main.js"></script>
登录后复制

将ts编译成js,自动生成目标js文件

tsc 目标js文件
登录后复制

在这里插入图片描述

在这里插入图片描述


ts基础类型

在定义变量的时候需要指定类型,且定义好类型以后就不能改变他的类型了 - 强类型。

数值型

let decLiteral: number = 6; // 十进制
let hexLiteral: number = 0xf00d; // 16进制
let binaryLiteral: number = 0b1010; // 二进制
let octalLiteral: number = 0o744; // 8进制

let num: Number = 5; // 此时大写Number类型可以赋值为数值对象类型
num = new Number(10);
登录后复制

布尔值

let isDone: boolean = false;let bool: Boolean = true; // 首字母大写的类型可以赋值为对象类型
登录后复制

boolean这种类型只能赋值两个值:true/false

var bool: boolean = true
 var bool: boolean = new Boolean(true)
登录后复制

Boolean这种类型除了上面的字面量方式的两个值,还可以使用构造函数方式

var bool: Boolean = false;var bool: Boolean = new Boolean(true)
登录后复制

字符串

var str: string = 'asdfasdf';var str1: String = new String('43563456')
登录后复制

数组

ts写的数组,其中的数据必须是同一个类型,但不指定长度
数组中所有数据的值类型必须是数字

var arr: number[] = [1,2,3];var arr: Array<string> = ['a','b'];
登录后复制

声明二维数组

var arr: number[]var brr: number[][] = [
    [1,2,3],
    [4,5,6]];
登录后复制

元组 Tuple

ts中的元组表示不同类型数据组成的集合,通常会固定长度,同样可以使用下标访问元素和给元素赋值

元组中就可以放不同类型的数据
元组在定义的时候就将长度固定了

var x: [string,number] = ['a',2];console.log(x);console.log(x[0]);
登录后复制

错误

x[2] = 20
登录后复制

不能加长度

let x: [string, number];x = ['hello', 10];x[2] = 'world'; // 不能加长度
登录后复制

可以给元素push一个值,这个值必须是string或number的类型,其他类型不允许

x.push('aaaa')
登录后复制

错误

 x.push(true) // 错误
登录后复制

当给元组中并不存在的下标进行赋值的时候,会使用联合类型:

x[3] = 'world'; // OK, 字符串可以赋值给(string | number)类型x
6] = true;// Error, 布尔不是(string | number)类型
登录后复制

枚举

ts中的枚举相当于在定义变量类型,这个类型有固定的取值范围,默认值从0开始,向后递增,使用指定的键来换换取到值,如果一个变量使用了这个类型,那他的值就必须从这个类型中选择,不能随便赋值:

枚举 - 必须使用指定的集合中的值
枚举类型,其实是给数字起了一些名字,让我们可以通过这个名字获取到对应的数字
默认情况,第一个名字对应的值是0,依次向后递增

enum Color {Red,Green,Blue};var c: Color = Color.Blue; // 2
登录后复制

如果给其中某一个名字赋值了,他后面的名字对应的值,是根据这里的值向后递增

enum Color {Red,Green = 5,Blue};var c: Color = Color.Blue; // 6
登录后复制

每个值可以指定

 enum Color {Red=3,Green = 4,Blue=2};
 var c: Color = Color.Blue; // 2
登录后复制

可以指定非数字的值

enum Color {Red='男',Green = '女',Blue='不男不女'};var c: Color = Color.Blue; // 不男不女
登录后复制

通过对应值的数字获取到对应的名字 - 名字是字符串类型

enum Color {Red,Green=5,Blue};var c: string = Color[6] // Blue
登录后复制

如果我们指定了其中的值是非数字型的,就不能使用这个骚操作了

enum Color {Red='red',Green = 'green',Blue='blue'};var c: string = Color['red']; // 这个地方的值必须是数字才行
登录后复制

Any

Any类型,表示弱类型,也就是当我们定义一个变量的时候,不能确定变量值的类型的时候,这个类型我们又爱又恨
使用:

var a:any = 20var b:any = 'asdfasdf'var c:any = [1,2,3]
登录后复制

注意:本来我们使用ts编写代码,为的是限制类型,减少安全隐患,但是如果使用了any类型,就跟直接写js一样了,失去了意义,所以若非迫不得已,尽量不要使用。

Void

这种类型,一般用于函数执行后,不使用return返回结果的时候,就指定返回结果是void
声明变量的时候不使用它 - 当函数没有返回值的时候,返回类型指定为void

function fn(a:number,b:number):void{
   console.log(a*b);}
登录后复制

Undefined

这种类型主要用于参数和返回值,用于变量毫无意义,因为定义一个变量指定为undefined类型时,以后也就只能是undefined类型了,函数中的用法:

function fn(num:number|undefined):number|undefined{
    return num;}
登录后复制

undefined - 未定义类型

var a:undefined = undefined
登录后复制

定义变量不用undefined,因为定义了没有用

通常会用在函数的参数里面
希望fn函数的参数a是可选项

function fn(a:number|undefined):void{
    console.log(a);}fn(undefined)
登录后复制

函数可选项
参数名后面,类型的冒号之前加 ? 表示这个参数是可选项
undefined通常用在函数返回值,如果返回的是undefined就需要在返回值的地方指定undefined类型

function fn(a?:number):number|undefined{
    return a;}fn()
登录后复制

Null

null类型 - 空 - 这个数据要被销毁啦
通常在定义复杂数据类型,且在后期需要给赋值为null的时候使用

var a:number|null = 10;
登录后复制

使用变量a计算 - 完成

让内存回收这个变量

a = null
登录后复制

Never

never类型表示永远不存在的值的类型,例如,一个函数中抛出的错误,函数中有死循环永远不可能返回 …

function fn():never{
    throw new Error('错误')}function fn():never{
    return fn()}fn()
登录后复制

Object

对象类型:

var obj: object = {
    name:"张三"}
登录后复制

错误写法 - 对象默认不允许添加键值对

obj.name = '张三';
登录后复制

类型断言

如果在一段代码执行后的类型种类的可能性比较多,就需要假设这是一种什么类型 - 这种操作就叫做断言。

如果一个表达式的结果有可能是多种类型,最终需要肯定其中一种

var abcd: any = [1, 2, 3, 4, 5];
登录后复制

断言abcd变量是一个数组

(abcd as [string,number]).push(6)(abcd as string) += 'ddd'
登录后复制

函数声明

在ts中,函数定义比起js中,多了参数类型和返回值的类型定义:
函数的定义,参数的类型声明,返回值的类型声明

function fn(a:number,b:number):number{
    // console.log(a+b);
    return a+b}var res = fn(1,2)
登录后复制

参数默认值

function fn(a:number,b:number=3):number{
    return a+b}var res = fn(1)
登录后复制

但是在表示参数为可选项的时候,写法稍有不同:
参数可选项 - ?表示可有可无

function fn(a:number,b?:number):number{
    if(!b){
        return a+5
    }
    return a+b}// var res = fn(1)var res = fn(1,3)
登录后复制

带有默认值的参数,必须放在所有参数的最后面
可选项参数,必须放在所有参数的最后面

展开运算符和合并运算符同样可以使用在ts中,但是要注意运算符后面的变量的类型设置。

计算不定实参的和

function  sum(...arr:Array<number>){
    var sum = 0;
    for(var i=0;i<arr.length;i++){
        sum += arr[i]
    }
    return sum;}var res = sum(1,2,3);console.log(res);
登录后复制

函数重载:通过 为同一个函数提供多个函数类型定义 来实现多种功能的目的。例:

function outputName(name:string):string{
    return "我叫"+name}var s1 = outputName(&#39;张三&#39;)console.log(s1);function outputAge(age:number):string{
    return "我今年"+age+"岁了"}var s2 = outputAge(12)console.log(s2);
登录后复制

有多个函数结构非常类似,可以声明一个函数的结构,让函数遵循这个结构

function output(name:string):string;  定义了一个函数结构 - 名字叫output
function output(age:number):string;

function output(name:any):any
{
    return "我今年"+name+"岁了";
}

var res = output(12)
console.log(res);

var res1 = output(&#39;李四&#39;)
console.log(res1);

var res2 = output(true)  报错的,因为函数的结构要求是参数string或number
console.log(res2);
登录后复制

ts中的类

定义

定义方式跟es6的定义方式类似

class 类名{
    constructor(){

    }}
登录后复制
class Person{
    // 静态属性 - 用类名直接调用的属性
    static weight:number;

    // 类的属性要定义在这里
    name:string; // 表示类中有一个属性叫name
    // 在ts类中,属性和方法前面可以加一个修饰符:
    /*
        public - 公开的 - 在哪里都能用
        protected - 受保护的
        private - 私有的
    */
    public age:number; // public可以省略的
    protected sex:string; // 受保护的只能在类里面用,类的外面不能用的
    private height:number; // 私有的只能在类里面使用,类外面不能用
    constructor(name:string,age:number,sex:string,height:number,weight:number){
        // 给属性赋值的时候,必须在这个类中是本来就有这个属性才行
        this.name = name

        this.age = age

        this.sex = sex

        this.height = height;

        // this.weight = weight;
        Person.weight = weight;

        this.init()
    }

    private init(){
        // console.log(this.age);
        // console.log(this.sex);
        console.log(this.height);
        console.log("这是初始化方法");
    }

    static fly(){
        console.log("飞的更高");
    }
}

var p = new Person(&#39;张三&#39;,12,&#39;男&#39;,120,150)
console.log(p);
// console.log(p.age);
// console.log(p.sex); // 受保护的属性不能类的外面使用
// console.log(p.height) // 私有属性不能类的外面使用 

// p.init()

console.log(Person.weight);
Person.fly()
登录后复制
登录后复制

继承

ts中类的继承和es6的继承是一样,使用extends关键字,然后在构造函数中调用super函数相当于在调用父类的构造函数。

如果子类和父类有同名的方法,在子类调用这个方法的时候先在子类里面找,如果子类没有再到父类里面找。

class Person{
    // 静态属性 - 用类名直接调用的属性
    static weight:number;

    // 类的属性要定义在这里
    name:string; // 表示类中有一个属性叫name
    // 在ts类中,属性和方法前面可以加一个修饰符:
    /*
        public - 公开的 - 在哪里都能用
        protected - 受保护的
        private - 私有的
    */
    public age:number; // public可以省略的
    protected sex:string; // 受保护的只能在类里面用,类的外面不能用的
    private height:number; // 私有的只能在类里面使用,类外面不能用
    constructor(name:string,age:number,sex:string,height:number,weight:number){
        // 给属性赋值的时候,必须在这个类中是本来就有这个属性才行
        this.name = name

        this.age = age

        this.sex = sex

        this.height = height;

        // this.weight = weight;
        Person.weight = weight;

        this.init()
    }

    private init(){
        // console.log(this.age);
        // console.log(this.sex);
        console.log(this.height);
        console.log("这是初始化方法");
    }

    static fly(){
        console.log("飞的更高");
    }
}

var p = new Person(&#39;张三&#39;,12,&#39;男&#39;,120,150)
console.log(p);
// console.log(p.age);
// console.log(p.sex); // 受保护的属性不能类的外面使用
// console.log(p.height) // 私有属性不能类的外面使用 

// p.init()

console.log(Person.weight);
Person.fly()
登录后复制
登录后复制

类的修饰符

在类中定义属性的时候,提供了3个修饰符:

  1. public:公有的 - 在类里面、子类中、类的外面都可以访问
  2. protected:受保护的 - 在类里面、子类中可以访问,在类外面不能访问
  3. private:私有的 - 在类里面可以访问,在子类和类的外面都不能访问

静态属性和方法

es5中静态方法使用:

// 模拟jquery的封装function $(element){
	return new Ele(element);}$.get = function(obj){
    }function Ele(element){
    this.element = document.getElementById("#"+element);}Ele.prototype.css = function(attr,value){
    if(value){
    	this.element.style[attr] = value;
    }else{
        return window.getComputedStyle(this.element)[attr];
    }}$("#box").css("color","red");
登录后复制

在ts中定义静态的属性和方法使用static关键字。在静态方法中无法访问到普通的属性,只能访问到静态的属性。

class Person{
    public name:string = "张三";
	static age:number = 20;
    constuctor(){

    }
    static print1(){
        console.log(this.name); // 访问不到
    }
	static print2(){
        console.log(Person.name); // 可以访问到
    }}Person.print1();Person.print2();
登录后复制

属性可以设置为只读

多态

面向对象的三大特点:封装、继承、多态

含义:多态就是说,父类定义一个方法不去实现,让继承它的子类去实现,这样每个子类都会有不同表现。多态其实也是继承的一种表现。

// 父类 - 动物类class Animal{
    public tui:string = "有腿";
    public eat(){
        console.log("喜欢吃");
    }
    public sport(){
        console.log("能走");
    }
    public tuiNum(){
        console.log("有多条腿");
    }}// 子类 - 人类class Person extends Animal{
    sport(){
        console.log("直立走");
    }
    tuiNum(){
        console.log("两条腿");
    }}var p = new Person();console.log(p.tui); // 有腿p.eat(); // 喜欢吃p.sport(); // 直立走p.tuiNum() // 两条腿// 子类 - 鸟类class Bird extends Animal{
    sport(){
        console.log("很少走,通常都在飞");
    }
    tuiNum(){
        console.log("两条腿");
    }}var b = new Bird();console.log(b.tui);b.eat();b.sport(); // 很少走,通常都在飞b.tuiNum(); // 两条腿// 子类 - 狗类class Dog extends Animal{
    sport(){
        console.log("通常都在跑,很少走");
    }
    tuiNum(){
        console.log("4条腿");
    }}var d = new Dog();console.log(d.tui);d.eat();d.sport(); // 通常都在跑,很少走d.tuiNum(); // 4条腿
登录后复制

效果:

多态的表现
在这里插入图片描述

**小总结:**多态就是多个子类继承自同一个父类,但是每个子类将继承下来的属性或方法做了改善,最终每个子类表现出来的结果是不一样的。

多态其实源于继承,也是方法的重载。

抽象类

在实际工作中,项目负责人通常会写一些标准(类似于大纲),然后将标准交给具体实现的攻城狮,由攻城狮将这个标准进行具体化开发。

ts中的抽象类就是为制作标准的。抽象类不能被实例化,只能被派生类继承并实现。

定义抽象类使用abstract关键字来修饰类。

abstract class Animate{
    public name:string;
	constructor(name:string){
		this.name = name;
    }}var ani = new Animate("动物"); // 报错class Dog extends Animate{
    constructor(name:string){
		super(name);
    }}var d = new Dog("小黄");
登录后复制

这种结构没有意义。跟普通的继承是一样的,并不能体现出标准的特殊。在抽象类中通常会有抽象方法 - 使用abstract修饰的方法。

抽象方法必须在抽象类中,且只需要定义方法结构,不要具体的实现。但是派生类中必须实现(完善)抽象方法。

abstract class Animate{
    public name:string;
	constructor(name:string){
		this.name = name;
    }
    abstract eat():void; // 抽象方法}class Dog extends Animate{
    constructor(name:string){
		super(name);
    }
    eat(){ // 实现了抽象方法
        consolelog("小狗吃粮食");
    }}
登录后复制

这个结构就能体现出标准的特殊:规定子类必须包含eat方法。

抽象方法只能放在抽象类中。

抽象类存在的意义就是被其他类继承,是其他类的基类。

接口

抽象类只能给方法定义标准,对于属性限制不够,所以ts设计了接口语法,它定义了属性和方法的规范,起到限制和规范的作用。接口并不关心这些类的内部状态数据,也不关心这些类里方法的实现细节,它只规定这批类里必须提供某些方法,提供这些方法的类就可以满足实际需要。

ts的接口跟别的主流服务器端语言的接口一样,同时还增加了更加灵活的接口类型,包括属性、函数、可索引和类等。

简单来说,接口也是在定义标准,只不过更加灵活和全面。

属性接口

属性接口专门为了约束属性而设计。

语法:

interface 接口名称{
    变量:类型;
    变量:类型;}
登录后复制

使用方式:

function printInfo(info:接口名称){
    console.log(info.属性名); // 属性名必须是接口定义过的,否则报错}
登录后复制

例:

// 以前对于数据的限制// 1.定义方法function printInfo():void{
    console.log(123);}printInfo();// 2.传入参数function printInfo(info:number):void{
    console.log(info);}printInfo(123);// 3.传入的参数对json限制function printInfo(info:{name:string}):void{
    console.log(info);}printInfo({
    name:"张三"});printInfo({ // 错误示例 - 键在函数中不存在
    sex:"男"});// 这种函数只能对一个键做限制,要做批量限制很麻烦,要写很多函数// 使用接口限制// 1.定义接口interface info {
    name:string;
    sex:string;}// 2.定义函数使用接口类型function printInfo(data:info){
    console.log(data.name);
    console.log(data.sex);
    // console.log(data.age); // 错误 - info中没有age键}// 3.使用printInfo({
    name:"张三",
    sex:"男",
    age:20 // 错误 - info中没有age键});var obj = {
    name:"张三",
    sex:"男",
    age:20}printInfo(obj); // 正确// 接口可以批量对变量进行约束 - 参数的顺序可以不一样,但是不能少参数
登录后复制

定义接口中的可选参数:

interface info{
    name:string;
    sex?:string;
    [propName:string]:any // 这里表示其他属性也可以加,也可以不加
}
// 这个接口表示name是必须,sex是可选项
// 在属性前面可以使用readonly来修饰属性不可以修改
登录后复制

例:

// 对jquery的ajax的封装$.ajax({
    type: "GET",
    url: "test.json",
    data: {username:$("#username").val(), content:$("#content").val()},
    dataType: "json"             });// 定义接口interface Config{
    type?:string;
    url:string;
    data?:string;
    dataType?:string;}// 使用接口类型封装ajaxfunction sendAjax(config:Config){
    var xhr = new XMLHttpRequest();
    }// 调用sendAjax({
    url:"",
    });
登录后复制

函数接口

函数接口是专门为了约束函数的参数和返回而设计。

语法:

interface 接口名称{
    (参数:类型):返回值类型}
登录后复制

例:

// 加密的接口interface encrypt{
    (key:string,value:string):string;}var md5:encrypt=function(key:string,value:string):string{
    //模拟操作
    return key+value;}console.log(md5(&#39;name&#39;,&#39;zhangsan&#39;));
登录后复制

可索引接口

可索引接口是对数组、对象等有索引的数据做约束。

对数组的约束接口:

interface userArr {
    [index:number]:string; // 表示索引必须为数字,数据必须是字符串}
登录后复制

使用:

var arr:userArr = ["张三","李四"]
登录后复制

对对象的约束:

interface userObj{
    [index:string]:string;}
登录后复制

使用:

var obj:userObj = {name:"张三"}
登录后复制

泛型

泛型:软件工程中,我们不仅要创建一致的定义良好的API,同时也要考虑可重用性。 泛型不仅能够支持当前的数据类型,同时也能支持未来的数据类型,这在创建大型系统时为你提供了十分灵活的功能。

通俗理解:泛型就是解决 类 接口 方法的复用性、以及对不特定数据类型的支持(类型校验)

泛型方法:

function getInfo<T>(value:T):T{
    return value;}getInfo<number>(123);getInfo<string>('aaa');
登录后复制

例:

// 约束函数传入number返回number,传入string返回string// 以前:function fn(a:number):number;function fn(a:string):string;function fn(a:any):any{
    return a;}// 使用泛型function fn<T>(a:T):T{
    return a;}fn<number>(234);fn<string>("abc");
登录后复制

命名空间

多人合作开发项目的时候,避免不了会有函数、变量、类等数据的命名冲突。但是ts不允许出现同名的类、函数、变量(const定义的),这时候就需要使用命名空间来解决这个问题。

命名空间其实就单独做一个作用域,在当前命名空间下的数据跟别的命名空间下的数据重名也不会产生冲突。

命名空间语法:

namespace A{ // namespace 命名空间名称{} 
    class Animal{
        constructor(){
            console.log("A命名空间下的动物类");
        }
    }}// 使用动物类的时候A.Animal()
登录后复制

例:
命名空间

工作中一个项目都是协作开发,每个人负责一个文件,避免不了函数、变量、类、接口会重名。
但是在ts文件,不允许类、函数、let、const 重名
命名空间就是解决这个问题的。
命名空间:就是开辟自己的作用域

// 定义命名空间:namespace 空间名字{}
namespace A{
    // 相当于定义了一个单独的作用域叫A
    export class Animal{
        name:string;
        constructor(name:string){
            this.name = name;
        }
    }
}

namespace B{
    export class Animal{
        age:number;
        constructor(age:number){
            this.age = age;
        }
    }
}

// 在这里实例化Animal类
// 使用命名空间:命名空间.数据
var a = new A.Animal("张三");
console.log(a.name); // 张三

var b = new B.Animal(20);
console.log(b.age); // 20
登录后复制

从结果中可以看到,同名的类处在不同的命名空间下是不会冲突的。

此时,A命名空间就是一个单独的模块,进行模块化开发的时候,需要将命名空间导出,也就是说一个命名空间就是一个模块,而不是一个单独的文件了。

例:

// 导出export namespace A{ // 将命名空间导出
    // 相当于定义了一个单独的作用域叫A
    export class Animal{
        name:string;
        constructor(name:string){
            this.name = name;
        }
    }}
登录后复制

导入的时候,导入当前文件,接收命名空间,通过命名空间来调用数据:

// 导入import { A } from "./demo"; // 导入的是一个命名空间var a = new A.Animal("张三"); // 实例化那个Animal
登录后复制

ts事件封装

为什么要封装?

因为在es5和es6中允许dom元素继承EventTarget,但是在ts中不允许继承。

所以需要重构EventTarget。

使用dispathEvent来抛发事件,需要使用Event。所以重构Event。

本质:观察者模式。

ts开发的规则

开发的时候通常都是在使用模块化开发

怎么进行模块化开发?一个模块一个类,通常类的首字母会大写,文件名称和类的名称保持一致。

封装

准备工作:

将ts配置文件中的module选项改成amd。

 "module": "amd",
登录后复制

更改输入输出目录:

"outDir": "./js", "rootDir": "./ts",
登录后复制

新建html,导入amd所使用的require.js。

配置导入文件以及异步推迟加载。

<script src="./require.js" data-main="./dist/Main"></script>
登录后复制

新建MyEvent.ts文件:

import MyTarget from "./MyTarget";export default class MyEvent{
    public type:string;
    [key:string]:any;
    public myTarget:MyTarget|null = null;
    public target:MyTarget|null = null;
    public data:any;
    constructor(type:string,data:any = null){
        this.type = type;
    }}
登录后复制

新建MyTarget.ts

import IListener from "./IListener";import MyEvent from "./MyEvent";export default class MyTarget{
    public listenerList:IListener = {};
    constructor(){

    }
    addEventListener(type:string,listener:Function):void{
        if(!this.listenerList[type]) this.listenerList[type] = [];
        this.listenerList[type].push(listener);
    }
    removeEventListener(type:string,listener:Function):void{
        if(!this.listenerList[type]) return;
        var index:number = this.listenerList[type].indexOf(listener);
        if(index>-1){
            this.listenerList[type].splice(index,1);
        }
    }
    dispathEvent(evt:MyEvent):boolean{
        var list:Function[] = this.listenerList[evt.type];
        if(!list) return false;
        evt.myTarget = this;
        evt.target = this;
        for(var i:number=0;i<list.length;i++){
            list[i].call(this,evt);
        }
        return true;
    }}
登录后复制

新建IListener.ts文件

export default interface IListener{
    [key:string]:Array<Function>;}
登录后复制

在Main.ts中使用:

import MyEvent from "./MyEvent";import MyTarget from "./MyTarget";var doc = new MyTarget();var ev = new MyEvent("zi");ev.a = 10;// var ev1 = new MyEvent("ziji");// ev1.b = 20;// console.log(doc);doc.addEventListener("zi",handler1);doc.addEventListener("zi",handler2);doc.addEventListener("ziji",handler2);doc.dispathEvent(ev);doc.dispathEvent(ev);// doc.dispathEvent(ev1);function handler1(e:MyEvent){
    console.log(e + "----------------");}function handler2(e:MyEvent){
    console.log(e + "||||||||||||||||||||");
    (e.target as MyTarget).removeEventListener("zi",handler2);}
登录后复制

效果:

第二次抛发的事件被删除
在这里插入图片描述

更多编程相关知识,请访问:编程入门!!

以上是一篇文章带你TypeScript入门(整理总结)的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

<🎜>:泡泡胶模拟器无穷大 - 如何获取和使用皇家钥匙
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆树的耳语 - 如何解锁抓钩
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系统,解释
3 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

热门话题

Java教程
1668
14
CakePHP 教程
1428
52
Laravel 教程
1329
25
PHP教程
1273
29
C# 教程
1256
24
5个常见的JavaScript内存错误 5个常见的JavaScript内存错误 Aug 25, 2022 am 10:27 AM

JavaScript 不提供任何内存管理操作。相反,内存由 JavaScript VM 通过内存回收过程管理,该过程称为垃圾收集。

Vue3+TypeScript+Vite怎么使用require动态引入图片等静态资源 Vue3+TypeScript+Vite怎么使用require动态引入图片等静态资源 May 16, 2023 pm 08:40 PM

问题:Vue3+TypeScript+Vite的项目中如何使用require动态引入类似于图片等静态资源!描述:今天在开发项目时(项目框架为Vue3+TypeScript+Vite)需要动态引入静态资源,也就是img标签的src属性值为动态获取,按照以往的做法直接是require引入即可,如下代码:写上后代码波浪线报错,报错提示:找不到名称“require”。是否需要为节点安装类型定义?请尝试使用npmi--save-dev@types/node。ts(2580)在进行了npmi--save-d

如何使用MySQL在TypeScript中实现数据类型转换功能 如何使用MySQL在TypeScript中实现数据类型转换功能 Jul 29, 2023 pm 02:17 PM

如何使用MySQL在TypeScript中实现数据类型转换功能引言:在开发Web应用程序时,数据类型转换是一个非常常见的需求。在处理数据库中存储的数据时,特别是使用MySQL作为后端数据库时,我们经常需要将查询结果中的数据按照我们所需的类型进行转换。本文将介绍如何在TypeScript中利用MySQL实现数据类型转换的功能,并提供代码示例。一、准备工作:在开

如何使用Redis和TypeScript开发高性能计算功能 如何使用Redis和TypeScript开发高性能计算功能 Sep 20, 2023 am 11:21 AM

如何使用Redis和TypeScript开发高性能计算功能概述:Redis是一个开源的内存数据结构存储系统,具有高性能和可扩展性的特点。TypeScript是JavaScript的超集,提供了类型系统和更好的开发工具支持。结合Redis和TypeScript,我们可以开发出高效的计算功能来处理大数据集,并充分利用Redis的内存存储和计算能力。本文将介绍如何

Vue3中怎么使用TypeScript Vue3中怎么使用TypeScript May 13, 2023 pm 11:46 PM

如何声明字段名为枚举的类型?根据设计,type字段应该是一个枚举值,不应该由调用方随意设置。下面是Type的枚举声明,共有6个字段。enumType{primary="primary",success="success",warning="warning",warn="warn",//warningaliasdanger="danger",info="info",}TypeSc

Vue3相较于Vue2的变化:更好的 TypeScript 类型推导 Vue3相较于Vue2的变化:更好的 TypeScript 类型推导 Jul 07, 2023 pm 01:05 PM

Vue3相较于Vue2的变化:更好的TypeScript类型推导Vue是一种流行的JavaScript框架,用于构建用户界面。而Vue3是Vue框架的最新版本,在Vue2的基础上进行了大量改进和优化。其中之一是在TypeScript类型推导方面的提升。本文将介绍Vue3在类型推导方面的改进,并且通过代码示例进行说明。在Vue2中,我们需要手动为Vue组件

使用Redis和TypeScript开发可扩展的前端应用程序 使用Redis和TypeScript开发可扩展的前端应用程序 Aug 01, 2023 pm 09:21 PM

标题:使用Redis和TypeScript开发可扩展的前端应用程序引言:在当今互联网时代,可扩展性是任何应用程序的关键要素之一。前端应用程序也不例外。为了满足用户日益增长的需求,我们需要使用高效可靠的技术来构建可扩展的前端应用程序。在本文中,我们将介绍如何使用Redis和TypeScript来开发可扩展的前端应用程序,并通过代码示例演示其应用。Redis简介

在PHP中使用TypeScript编写更好的代码 在PHP中使用TypeScript编写更好的代码 Jun 19, 2023 pm 06:31 PM

随着JavaScript的不断发展,前端工程师们已经逐渐意识到JavaScript本身存在的一些问题,例如缺乏类型检查和模块化,这些问题在大型项目中经常会造成混乱和错误。为了解决这些问题,TypeScript应运而生,成为前端开发中越来越受欢迎的语言。而在后端开发领域中,PHP一直是一种极其流行的脚本语言。因此,结合TypeScript来开发PHP的应用程序

See all articles