IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> 学习TypeScript这些知识点就够了 -> 正文阅读

[JavaScript知识库]学习TypeScript这些知识点就够了

前言

这篇blog是自己学习TS时的笔记,如果您想学习TS,发现官网不太友好,可以参考一下我这篇文章。

如果您想参考本篇文章的所有代码,请戳这里:实验代码

TypeScript概述

在前端开发领域有JavaScript语言,为什么还要有TypeScript?
TypeScript同JavaScript相比,最大的特点是强类型,支持静态和动态类型,和JavaScript不同,这种强类型相比弱类型,可以在编译期间发现并纠正错误,降低了试错的成本也提升了代码的规范性。

TS(TypeScript简称) 是 JS(JavaScript简称)的超集。在这里插入图片描述
其实TS可以认为是在JS的基础上增加了类型系统和 一些新的特性和语法,在运行时,需要将TS编译成JS。

安装TypeScript和配置项目文件

全局安装TypeScript

npm install -g typescript

配置项目文件(tsconfig.json)
在项目根目录下运行tsc --init,这个文件中可以设置一些配置项,方便我们针对不同的项目要求。

我们主要配置以下几项:

"target": "es5",                                /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', 'ES2021', or 'ESNEXT'. */
"module": "commonjs",                           /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
"outDir": "./dist",                              /* Redirect output structure to the directory. */
"rootDir": "./src",                             /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */

配置文件后,在执行命令行:tsc后,会根据tsconfig.json中的配置将TS代码转化为JS代码。

基础类型

与JS一样,TS也提供了一些基本类型:数字,字符串,布尔值,Any,void , Null 和 Undefined。
数字,字符串,布尔值:

// 数字
let decLiteral: number = 6;
let hexLiteral: number = 0xf00d;

// 字符串
const hName: string = '胡三疯';

// 布尔
let isLet: boolean = true; // false / true

Any
any表示任何类型,当我们在编程过程中对于一个变量不确定什么类型数据时,可以使用Any

//  Any
let anyVariable: any = 4
anyVariable = 'this is anyVariable';

void
void 表示没有任何类型,在某个函数没返回值需要使用void,对于变量作用不大,如果用于变量的话,只能赋值ndefined 和 null,建议不要对变量使用此种类型

// void
function consoleFun(): void {
    console.log("this is no return");
}

let unusable: void = undefined; // undefined / null

Null 和 Undefined
在TS中,这两种类型用处不大,特别在严格模式下,他们只能赋值给他们本身的类型和 void。

let u: undefined = undefined;
let n: null = null;

Symbols

symbol 也是一种基础类型,只不过是ECMAScript 2015之后新出的基础类型

let sym = Symbol();

当我们使用symbol 时,编译器会报错,提示Symbol 这个找不到声明,为什吗那?

因为在tsconfig.json文件中,指定的编译后的JS是"target": "es5",对于es5以前的内置对象所对应的声明(标准库)会有,但是es6+之后所对应的标准库,我们需要在lib属性中自己新增,注意如果我们要把所有使用的标准库都在这里重新写,因为会覆盖默认的所有标准库。

"lib": ["ES2015","DOM"]

枚举类型

枚举类型一般用于某个对象有固定的几个值。在JS中,是没枚举这个类型的,一般使用对象的方式模仿枚举。

当是数字枚举时,我们可以不指定具体的枚举值,第一个会被赋值为0,后面的依次累加;若指定第一个值,后边的值若不指定,也会依次累加;当定义字符串枚举时,我们只有老老实实的给每项赋值

enum status {
    publish = 0,
    Unpublished = 1
}

let blog = {
    title:"我是胡三疯",
    content: "胡三疯是个好孩子。。。。。。",
    postStatus: status.Unpublished
}

上边枚举在编译成JS对象时会被编译成双向键值对对象,也叫反向映射。如若不想被编译成这样,可以在enum前加上const,会被编译成对象

const enum status {
    publish = 0,
    Unpublished = 1
}

Object 类型

Object 类型并不单指对象类型,是指除了原始类型外的所有类型;我们定义对象类型的时候可以使用一种类似对象字面量的一种语法,但是对于对象类型的使用建议使用接口的方式,更专业

let obj1: Object = function(){}// {name: "胡三疯"} []

let obj2:{name: string, age: number} = {name: "胡三疯", age:18}

export {}

数组类型

对于数组类型的定义方式有两种:

  • Array 泛型
  • 元素类型 []
// 1. Array泛型
let arr1: Array<number> = [1, 4, 18]
// 2. 元素类型[]
let arr2: number[] = [1, 5, 12, 15]

对于元素数组指定好具体的类型,可以让我们在程序中省去对元素类型的判断

元组类型

元组类型是一种明确元素数量和类型的数组,是一种混合元素类型的数组,使用数组字面量的方式定义。

let tuple: [number, string] = [18, "胡三疯"]

函数类型

在定义函数时,需要制定参数的类型,返回值的类型可有可无,因为函数能够推断出返回值的类型

在定义函数时,有两种方式:

  • 函数声明式
  • 函数表达式
// 1. 函数声明
function add1(x:number, y:number):number {
    return x + y;
}

// 2. 函数表达式
const add2 = function(x:number, y:number):number {
    return x + y;
}

TypeScript里的每个函数参数都是必须的。若使某个参数变成可选参数,可以在参数名旁使用 ?实现可选参数的功能;也可以给某个参数设置默认值。

// 可选参数
function add3(x:number, y?:number):number {
    y = y ? y :0
    return x + y;
}
// 默认值
function add4(x:number, y:number = 0):number {
    return x + y;
}

隐式类型推断

当我们声明一个变量时,如果没有表明类型,TS会根据变量值来判断变量的类型。这样有时间虽然可以简化我们的代码,但是使用时不建议这样使用。

// age 会被推断为 number
let age = 18;

// foo 会被推断为 any
let foo;
foo = 100
foo = "胡三疯"

类型断言

在我们程序中,若在类型推断中不能确定具体类型,在我们进行下步操作时,编译器肯定会报错。这时如果我们能够明确知道是什么类型的数据,我们就可以断言数据类型,减少处理的操作。

类型断言可以通过以下两种方式解决:

  • as
  • <数据类型>
let numArr = [100, 120, 150]

// 类型系统判断 num 是number 或 undefined
const num = numArr.find(i => i > 100 )
// const square = num * num;  // num is possibly 'undefined'

// 类型断言
const num1 = num as number

const num2 = <number> num

const square1 = num1 * num1;
const square2 = num2 * num2;

接口

接口是一种规范,经常用于定义对象类型的变量。

interface Person {
    name: string;
    age: number
}

let sanFengHu: Person =  {
    name: "胡三疯",
    age: 18
}

可选属性
接口里的属性不全都是必需的。 有些是只在某些条件下存在,或者根本不存在。如:hobby

interface Person {
    name: string;
    age: number;
    hobby ?: string
}

只读属性
一些对象属性只能在对象刚刚创建的时候修改其值。 你可以在属性名前用 readonly来指定只读属性:

interface Person {
    name: string;
    age: number;
    hobby ?: string
    readonly id: string
}

let sanFengHu: Person =  {
    name: "胡三疯",
    age: 18,
    id:"411402199908806666"
}

动态成员
在接口定义时,我们不确定有什么属性可以使用动态成员

// 动态成员
interface dynamicProperty {
    [property: string]: string
}

let dynamicObj: dynamicProperty = {
    key1: "value1", 
    key2: "value2", 
}

在ES6之前,JS是通过函数和原型继承的方式来实现。在ES6+之后,使用class来实现,在TS中也是使用Class来实现。

class Person {
    name:string;
    age:number;
    constructor(name: string, age:number) {
        this.name = name;
        this.age = age
    }

    say(){
        console.log("my name is" + this.name +",age" + this.age)
    }
}

let person = new Person('胡三疯', 18);
person.say();

属性修饰符

针对对象中的属性,有几种修饰符来限定属性的访问范围:

  • public 默认属性,可以自由的访问程序里定义的成员
  • private 能在声明它的类的外部访问
  • protected 与private功能类似,但是protected成员在派生类中仍然可以访问
// private 栗子
class Animal {
    private name: string;
    constructor(theName: string) { this.name = theName; }
}

new Animal("Cat").name; // 错误: 'name' 是私有的.

//  protected Vs private
class Person {
    protected name: string;
    private age: number;
    constructor(name: string, age:number) { this.name = name; this.age = age}
}

class Employee extends Person {
    constructor(name: string, age: number) {
        super(name,age)
    }
    public getElevatorPitch() {
        return `Hello, my name is ${this.name} and I work in ${this.age}.`;
    }
}

let howard = new Employee("Howard",18);
console.log(howard.getElevatorPitch());

readonly只读属性

只读属性只能在声明或构造函数里被初始化

class Person {
    name:string;
    readonly gender:string;
    constructor(name: string, gender:string) {
        this.name = name
        this.gender = gender
    }
}

let sanfeng_hu = new Person("sanfeng_hu", "man");
sanfeng_hu.gender = "man"  // Cannot assign to 'gender' because it is a read-only property.

抽象类

对于一些顶层的类我们可以作为抽象类,比如 将动物作为抽象类,然后小猫,小狗…作为具体类,在抽象类实现的方法,子类都可以继承,同时也可以定义一些抽象方法在子类中实现。
定义抽象类和抽象方法只需要在类名前加abstract即可。

// 抽象类
abstract class Animal {
    abstract makeSound(): void;
    move(): void {
        console.log('roaming the earch...');
    }
}

// 子类
class Dog extends Animal {
    // 抽象方法实现
    makeSound():void {
        console.log("----makeSound++++++++")
    }
}

let dog = new Dog()
dog.move()
dog.makeSound()

export {}

类和接口

在一些类中有共同的方法,但是具体实现不同时,我们可以定义一个接口规定这些类必须的方法,具体实现放到具体类中

export {}

interface runAndEat {
    eat():void;
    run():void;
}

class Dog implements runAndEat {
    eat():void {
        console.log("dog---eat");
    }
    run():void {
        console.log("dog---run");
    }
}

class Pig implements runAndEat {
    eat():void {
        console.log("Pig---eat");
    }
    run():void {
        console.log("Pig---run");
    }
}

let dog = new Dog()
let pig = new Pig()
dog.eat()
dog.run()

pig.eat()
pig.run()

泛型

泛型是指函数在定义时不确定具体类型,等到具体调用时再确定,并且可以保证传入类型和传出类型是同一类型。

// 数字数组
function createNumArr(length:number, item: number):number[] {
    return Array(length).fill(item)
}

// 字符串数组
function createStrArr(length:number, item: string):string[] {
    return Array(length).fill(item)
}

// 使用泛型
function createArr<T>(length:number, item: T):T[] {
    return Array(length).fill(item)
}

let numArr1 = createNumArr(2, 6);
let strArr1 = createStrArr(2, "hh")

let numArr2 = createArr(2, 7)
let strArr2 = createArr(2, "dd")

console.log(numArr1,strArr1,numArr2,strArr2)

export {}

TypeScript作用域问题

在我们对每个特性做练习的时候,会出现相同变量名的情况,因为这些变量是在全局作用域下,所以会报重复命名的错误,那么我们只需要将每个文件放在单独作用域内就行了,可以使用立即执行函数或 ES Modules

let sym1 = Symbol();
export {}

在这里我使用 ES Modules,只需要在文件中加上:export {}

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-07-22 22:57:51  更:2021-07-22 22:58:18 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/6 10:48:38-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码