首頁 > web前端 > 前端問答 > 一篇文章帶你TypeScript入門(整理總結)

一篇文章帶你TypeScript入門(整理總結)

WBOY
發布: 2022-01-24 17:22:42
轉載
2508 人瀏覽過

這篇文章為大家帶來了關於TypeScript入門的相關知識,希望對大家有幫助。

一篇文章帶你TypeScript入門(整理總結)

前言

ts是什麼? ts其實是TypeScript的一個簡稱,就跟JavaScript簡稱為js一樣,官方給的解釋是,ts它是js的超集,其實js的程式碼本質上都是ts編譯的,例如寫一個js程式碼document.write () ,上面的提示就是ts,如圖:

一篇文章帶你TypeScript入門(整理總結)
系統裡面寫的是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. Google也大力支持TypeScript的推廣,Google的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
登入後複製

一篇文章帶你TypeScript入門(整理總結)

npm install -g typescript
登入後複製

一篇文章帶你TypeScript入門(整理總結)

偵測是否安裝成功:

tsc -v
登入後複製

ts檔案的後綴是ts,編譯指令:

tsc 被编译的文件
登入後複製

會在被編譯檔案的同級目錄下產生一個同名的js檔案。

產生自訂名稱路徑的檔案:

tsc 被编译的文件 --outFile 编译后的文件路径
登入後複製

初始化命令:

tsc --init
登入後複製

執行初始化命令後,會產生一個tsconfig.json文件,如下:

一篇文章帶你TypeScript入門(整理總結)

其中常用配置项说明:

代表ts要转换后js版本

"target": "es5"
登入後複製

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

"module": "amd"
登入後複製

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

"outDir": "./"
登入後複製

一篇文章帶你TypeScript入門(整理總結)

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

tsc -w
登入後複製

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

<script></script>
登入後複製
登入後複製

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

tsc 目标js文件
登入後複製

一篇文章帶你TypeScript入門(整理總結)

一篇文章帶你TypeScript入門(整理總結)


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'];</string>
登入後複製

声明二维数组

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><p>函数重载:通过 为同一个函数提供多个函数类型定义 来实现多种功能的目的。例:</p>
<pre class="brush:php;toolbar:false">function outputName(name:string):string{
    return "我叫"+name}var s1 = outputName('张三')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('李四')
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('张三',12,'男',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('张三',12,'男',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条腿
登入後複製

效果:

多态的表现
一篇文章帶你TypeScript入門(整理總結)

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

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

抽象类

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

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('name','zhangsan'));
登入後複製

可索引接口

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

对数组的约束接口:

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');</string></number></t>
登入後複製

例:

// 约束函数传入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");</string></number></t>
登入後複製

命名空间

多人合作开发项目的时候,避免不了会有函数、变量、类等数据的命名冲突。但是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></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><p>新建IListener.ts文件</p>
<pre class="brush:php;toolbar:false">export default interface IListener{
    [key:string]:Array<function>;}</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入門(整理總結)

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

以上是一篇文章帶你TypeScript入門(整理總結)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:csdn.net
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板