TypeScript
什么是TypeScript?
- TypeScript是由微软开发的一款开源的编程语言
- TypeScript是JavaScript的超集,遵循最新的ES5 ES6规范,TypeScript扩展了JavaScript的语法
- TypeScript更像后端 Java c# 这样的面向对象语言可以让js开发大型企业项目
- 谷歌也在大力支持TypeScript的推广,React ,VUE 都集成了TypeScript
TypeScript安装
安装
-- 安装
npm install -g typescript
检查是否安装成功
tsc -v
编译
-- 将.ts文件转换成.js文件
tsc 文件名.ts
VsCode配置TypeScript
vscode配置TypeScript文件的自动编译
-
在.ts文件夹下运行cmd 执行 tsc --init 命令 自动生成tsconfig.json配置文件
更改tsconfig.json配置文件 “outDir”: “./js”, 编译后js输出的目录
- 任务 ——>运行任务 ——> 监视tsconfig.json 文件
vscode监视tsconfig报错
1.管理员身份运行vs code
2.在终端执行:get-ExecutionPolicy,显示Restricted
3.在终端执行:set-ExecutionPolicy RemoteSigned
4.在终端执行:get-ExecutionPolicy,显示RemoteSigned
数据类型
TypeScript中为了使编写的代码更规范,更利于维护,增加了类型校验,在声明变量同时为它指定数据类型
格式 : 变量名: 数据类型 = 值
布尔类型(boolean)
// 布尔类型(boolean)
let flag:boolean = false;
console.log(flag);
数值类型(number)
// 数值类型(number)
let num:number = 20;
console.log(num);
// 如果没有值不是number类型那么ts编译会报错 但是浏览器可以正常输出
// let num1:number = "20";
// console.log(num1);
字符串类型(string)
// 字符串类型(string)
let str:string = "Hello";
console.log(str);
数组类型(Array)
// 数组类型(Array) 直接为数组的每个元素指定同一类型
// 数组声明方式一 数组声明时指定 数组类型
let arr:number[] = [1,2,3,4];
console.log(arr);
// 数组声明方式二 Array数组类型 给它指定泛型
let arr1:Array<string> = ["1","2","3"];
console.log(arr1);
// 数组声明方式三 any类型
let arr2:any[] = ["this",0,"me"];
console.log(arr2);
元组类型(tuple)
// 元组类型(tuple) 属于数组的一种 为数组的每一个元素指定一个类型
let arr3:[string,number,boolean] = ["this",1,true];
console.log(arr3);
枚举类型(enum)
// 枚举类型(enum)
/*
声明方式
enum 枚举名{
标识符=[值]
}
*/
enum Color{
red,
blue,
yellow="yellow"
}
// 如果枚举没有给枚举元素赋值那么指向的是当前元素的下标
console.log(Color.blue);
// 给枚举元素赋值 直接输出当前元素的值
let y:Color = Color.yellow;
console.log(y);
任意类型(any)
// 任意类型(any) 可以随意指定类型
let sum:any = 123;
sum = "456";
console.log(sum);
null和undefined
// null和undefined 其他类型(never类型)数据类型的子类型
// 声明未赋值 undefined
let str1:string;
console.log(str1); // 输出 undefined 但是 ts编译会报错
// 指定string 或 undefined 如果不赋值 输出undefined编译不会出错
let str2: string | undefined = "Hello";
console.log(str2);
// null 类型 只能为null
let str3:null = null;
console.log(str3);
// 为一个元素指定多种类型
let str4:string | undefined | null;
str4 = "Hello";
console.log(str4);
void类型
// void类型 :typescript中的void表示没有任何类型,一般用于定义函数的时候函数没有返回值
// 指定foo函数没有返回值
function foo():void{
console.log("void");
}
foo();
// 指定函数返回值类型
function get():number{
return 100;
}
console.log(get());
never类型
// never类型:是其他类型(包括null,undefined)的子类型,代表从来不会出现的值,
// 这意味着never声明的变量只能被never类型所赋值
var a:undefined;
a = undefined;
console.log(a);
var b:null;
b = null;
console.log(b);
// 从未出现的值 一般never类型不常用
var err:never;
err = (()=>{throw new Error("Error")})();
函数
函数定义
// 函数定义
// 定义无返回值
function fun():void{
console.log("void")
}
fun();
const fun1 = function():void{
console.log("字面量函数void")
}
fun1();
// 定义带返回值的函数
function fun2():string{
return "返回值类型是string";
}
console.log(fun2());
const fun3 = function():string{
return "字面量函数带返回值";
}
console.log(fun3());
函数参数
// 函数参数 在参数后面指定参数的类型
function fun4(name:string){
return name;
}
console.log(fun4("小牛"));
可选参数
// 可选参数
// 有时候需要age这个参数 有时候不需要 我们可以给age设置可选
function fun5(name:string,age?:number):any{
// 如果有age这个参数 我们返回 name 和 age
if(age){
return `${name} --- ${age}`;
}
// 如果没有我们只返回name
return `${name}`;
}
console.log(fun5("牛小牛",22));
// 注意:可选参数尽量写在形参列表最后
默认参数
// 默认参数
// 在参数定义时给它赋上默认值
function fun6(name:string,age:number=20):any{
return `${name}---${age}`;
}
console.log(fun6("小牛",21));
剩余参数
// 剩余参数 ... 用于参数列表不确定参数个数使用
// 注意:剩余参数写在形参列表最后
function fun7(a:number,...result:number[]){
let num:number = a;
for(let v of result){
num += v;
}
return num;
}
console.log(fun7(1,2,3,4,5));
函数重载
// 函数重载 ts支持函数重载
// 函数重载 : 函数名相同参数列表不同(参数的个数,顺序,类型)有一个不同就都不相同
function getInfo(name:string):string;
function getInfo(age:number):number;
function getInfo(str:any):any{
if(typeof str === "string"){
return str;
}else{
return str;
}
}
console.log(getInfo("hello"))
// 多个参数重载
function getData(name:string):string;
function getData(name:string,age:number):any;
function getData(name:string,age?:number):any{
if(age){
return `${name} --- ${age}`;
}
return `${name}`
}
console.log(getData("小牛",22));
箭头函数
// 箭头函数 es6箭头函数一样
setTimeout(()=>console.log("箭头函数的this依然指向上下文"));
类
ES5类
// es5类
// 最简单的类
function Student(){
this.name = "小牛";
this.age = 20;
}
const s = new Student();
console.log(s.name);
console.log("-----------------------")
// 构造函数和原型链上增加方法
function Person(){
this.name = "小牛";
this.age = 21;
this.run = function(){
console.log(this.name + "在运动");
}
}
// 原型链上的属性会被多个实例共享 构造方法不会
Person.prototype.sex = "man";
Person.prototype.work = function(){
console.log(this.name + "在工作");
}
var p = new Person();
console.log(p.name);
p.run();
p.work();
console.log("-----------------------")
// 类里面的静态方法
function Stu(){
this.name = "小牛"; // 属性
this.age = 21;
this.run = function(){ // 实例方法
console.log(this.name + "在运动");
}
}
// 静态方法只能被类调用 不能被实例调用
Stu.getInfo = function(){
console.log("我是静态方法")
}
// var stu = new Stu();
// stu.getInfo();
// 类 调用静态方法
Stu.getInfo();
console.log("-----------------------")
// 冒充继承
function Girl(){
this.name = "MM";
this.age = 20;
this.run = function(){
console.log(this.name + "运动")
}
}
// 原型链
Girl.prototype.color = "pink";
Girl.prototype.work = function(){
console.log(this.name + "工作")
}
// Web类 继承Girl类 原型链 + 冒充继承
function Web(){
// 对象冒充继承 call apply bind
Girl.call(this);
}
var w = new Web();
// 冒充继承可以继承构造函数的属性和方法
w.run();
// 冒充继承可以继承构造函数中的属性和方法 但是不能继承原型链的属性和方法
// w.work();
console.log("-----------------------")
// 原型链实现继承 继承Girl类
function Father(){
this.name = "牛小牛";
this.age = 22;
this.run = function(){
console.log(this.name + "运动");
}
}
Father.prototype.work = function(){
console.log(this.name + "工作")
}
function Man(){
}
// 原型链继承 可以继承构造函数的属性和方法,也可以继承原型链上的属性方法
Man.prototype = new Father();
var m = new Man();
console.log(m.age);
m.run();
m.work();
console.log("-----------------------")
// 原型链继承的问题?
function F(name,age){
this.name = name;
this.age = age;
this.run = function(){
console.log(this.name + "运动")
}
}
F.prototype.sex = "man";
F.prototype.work = function(){
console.log(this.name + "工作")
}
var f = new F("花花牛",21);
f.work();
function FF(name,age){
}
FF.prototype = new F();
var ff = new FF("雨花雨",21);
// 原型链继承传参的问题
ff.run();
console.log("-----------------------")
// 原型链 + 冒充继承组合继承模式
function P(name,age){
this.name = name;
this.age = age;
this.run = function(){
console.log(this.name + "运动")
}
}
P.prototype.sex = "man";
P.prototype.work = function(){
console.log(this.name + "工作")
}
function PP(name,age){
P.call(this,name,age);
}
PP.prototype = new P();
var pp = new PP("雨花雨",22);
pp.run();
pp.work();
console.log("-------------------------")
// 原型链 + 冒充继承的另一种方式
function Man(name,age){
this.name = name;
this.age = age;
this.run = function(){
console.log(this.name + "运动")
}
}
Man.prototype.sex = "man";
Man.prototype.work = function(){
console.log(this.name + "工作")
}
function M(name,age){
Man.call(this,name,age);
}
M.prototype = Man.prototype;
var m = new M("奶牛",21);
m.run();
m.work();
ES6类
// 类的声明
class Person{
// 构造函数
constructor(name,age) {
this.name = name;
this.age = age;
}
// 定义方法
show(name){
console.log(this.name + "显示")
}
}
let p = new Person("小牛",21);
console.log(p.name);
console.log(p.age);
p.show();
console.log("------------------------------")
// 静态成员
class Phone{
// static 修饰的属性和方法都是静态的只属于类
static name = "Phone";
static show(){
console.log("静态方法")
}
}
// 静态成员不能被实例化
console.log(Phone.name);
Phone.show();
console.log("------------------------------")
// 继承 extends super
class A{
constructor(name,age){
this.name = name;
this.age = age;
}
eat(){
console.log("吃饭")
}
}
class B extends A{
constructor(name,age,color,size){
super(name,age);
this.color = color;
this.size = size;
}
// 重写父类的方法
eat(){
console.log("吃晚饭")
}
}
const b = new B("小牛",20,"skyblue",180);
console.log(b.name);
b.eat();
console.log("------------------------------")
// get set 方法
class Smart{
// 用来获取属性的方法
get price(){
return "get方法获取属性"
}
// set 的时候 需要传入一个参数
set price(newValue){
console.log("set方法设置了属性")
}
}
const smart = new Smart();
smart.price = "set方法设置";
console.log(smart.price)
TS类的声明
// ts 类的声明
class Person{
name:string; // 属性 默认public修饰
age:number;
constructor(name:string,age:number){ // 构造函数 实例化的时候触发
this.name = name;
this.age = age;
}
show():void{
console.log(this.name + "ts类中的方法")
}
}
const person = new Person("小牛",21);
console.log(person.name);
console.log(person.age);
person.show();
类的get set方法
get 和 set方法用于获取和设置类的属性
// 类的get set方法
class Student{
name:string;
constructor(name:string) {
this.name = name;
}
// 用来设置属性的值
setName(name:string):void{
this.name = name;
}
// 用来获取属性的值
getName():string{
return this.name;
}
}
const student = new Student("大牛");
// 获取没有设置之前的值
console.log(student.getName());
// 设置值
student.setName("二牛")
// 获取设置之后的值
console.log(student.getName());
继承
继承使用关键字extends,调用父类使用super,子类继承父类的属性和方法,并且子类可以改写父类的属性和方法
// 类的继承 extends super
class Phone{
brand:string;
price:number;
constructor(brand:string,price:number){
this.brand = brand;
this.price = price;
}
show():void{
console.log("Phone.show");
}
}
class SmartPhone extends Phone{
color:any;
size:any;
constructor(brand:string,price:number,color:any,size:any){
super(brand,price);
this.color = color;
this.size = size;
}
// 重写父类的方法
show():any{
console.log("SmartPhone.show")
}
}
const smartPhone = new SmartPhone("iphoneX",7999,"black",5.5);
console.log(smartPhone.brand);
console.log(smartPhone.price);
console.log(smartPhone.color);
console.log(smartPhone.size);
smartPhone.show();
访问修饰符
typescript为我们提供了三种访问修饰符
public 公共的 作用范围 本类 子类 类外部
protected*保护的 作用范围 本类 子类
private 私有的 作用范围 本类
// 访问修饰符
/*
public 公共的 作用范围 本类 子类 类外部
protected 保护的 作用范围 本类 子类
private 私有的 作用范围 本类
*/
class School{
public name:string;
protected age:number;
private sex:string;
constructor(name:string,age:number,sex:string){
this.name = name;
this.age = age;
this.sex = sex;
}
show():any{
console.log("public---->" + this.name)
console.log("protected---->" + this.age)
console.log("private---->" + this.sex)
}
}
const school = new School("xiaoniu",21,"man");
console.log(school.name);
school.show();
// age sex 分别是用 protected private 在类外部不能访问所以编译出错
// console.log(school.age);
// console.log(school.sex);
class Teacher extends School{
constructor(name:string,age:number,sex:string){
super(name,age,sex);
}
show():any{
console.log("public---->" + this.name)
console.log("protected---->" + this.age)
// sex 是private修饰的 继承过来的 sex是无法访问的所以会报错
console.log("private---->" + this.sex)
}
}
const teacher = new Teacher("daniu",22,"sex");
console.log(teacher.name);
teacher.show();
静态成员
static修饰的静态成员当类加载时就存在 只能被类调用 不能实例化
// 静态成员
// 静态成员当类加载时就存在 不能被实例化
class Per {
public name:string;
public age:number;
// static声明 静态属性
static sex:any = "man";
constructor(name:string,age:number) {
this.name = name;
this.age = age;
}
static eat():void{
console.log("静态方法")
}
}
const p = new Per("小牛",21);
console.log(p.name)
// 静态成员只能被类调用
console.log(Per.sex)
Per.eat();
多态
多态 :父类定义的方法不一定实现,让继承它的子类去实现,每个子类都有不同的表现形式
class Animal{
public name:string;
constructor(name:string){
this.name = name;
}
eat(){
console.log("吃的方法!")
}
}
class Dog extends Animal{
constructor(name:string){
super(name);
}
eat(){
console.log(this.name + "吃骨头")
}
}
const dog = new Dog("小狗狗");
dog.eat();
class Cat extends Animal{
constructor(name:string){
super(name);
}
eat(){
console.log(this.name + "吃猫粮")
}
}
const cat = new Dog("小花猫");
cat.eat();
抽象类
typescript中的抽象类:它是提供其他类继承的基类,不能被直接实例化
abstract 关键字修饰的抽象类和抽象方法, 抽象类中的抽象方法不包含具体的实现并且必须在派生类中实现
abstract 修饰的方法只能在抽象类中
// 抽象类
abstract class Animal {
public name:any;
constructor(name:any){
this.name = name;
}
abstract eat():any;
// 非抽象方法 子类可以不实现它
say(){
console.log(this.name + "在说话")
}
}
class Dog extends Animal{
constructor(name:any){
super(name);
}
// 抽象类的子类必须实现抽象类的抽象方法
eat(){
console.log(this.name + "吃骨头")
}
}
class Cat extends Animal{
constructor(name:any){
super(name);
}
eat(){
console.log(this.name + "吃猫粮")
}
}
const cat = new Cat("小花猫");
cat.eat();
接口
接口:是一种规范的定义,它定义了行为和动作的规范,接口起到了一种限制和规范的作用,接口定义了某一批类所需要的遵循的规范,接口不关心这些类的内部状态数据,也不关心这些类里方法实现的细节,它只规定了这批类必须提供某些方法,提供了这些方法的类就可以满足实际需要,typescript中的接口类似于java,同时还增加了更灵活的接口属性,包括属性,函数,可索引和类等。
json约束
约束了json的格式
// 接口 interface
interface Conn{
host:string;
port:number;
username:string;
password:string
}
// 约束了参数 及参数类型
function Connection(info:Conn):any{
return `${info.host} --- ${info.port} --- ${info.username} --- ${info.password}`;
}
// 第一种传参方式
Connection({
host:"localhost",
port:3306,
username:"root",
password:"root"
})
const conn = {
host:"localhost",
port:3306,
username:"root",
password:"root"
}
// 第二种传参方式
console.log(Connection(conn))
可索引接口
可索引接口用来约束数组的格式
// 可索引接口 约束数组
interface Arr{
// 约束数组 下标为number类型 的一个string类型数组
[index:number]:string;
}
const ones:Arr = ["A","B","C"];
console.log(ones[0])
对象约束
// 对象的约束
interface Obj{
[key:string]:any
}
const obj:Obj = {"name":"小牛"}
console.log(obj["name"])
可选操作符
属性?:数据类型
表示可选 可以写也可以不写 可以通过编译
interface IPerson{
firstName:string,
// ? 可选操作符
lastName?:string,
sayHi:()=>string
}
// 接口约束对象
const customer:IPerson = {
firstName:"Tom",
lastName:"Tim",
sayHi:():string=> "Hi Tom"
}
console.log(customer);
类类型接口
// 类类型接口 约束类
interface Cla{
name:string;
eat():any;
}
// 类类型接口 类只能用 implements 实现
class Birage implements Cla{
public name = "goods";
eat(){
console.log("吃东西")
}
}
const br = new Birage();
console.log(br.name)
br.eat();
联合类型和接口
// 联合类型和接口
interface RunOptions{
program:string;
commandline:string[] | string | (()=>string);
}
const options:RunOptions = {
program:"tim",
// 参数可以是字符串数组
// commandline:[
// "小牛",
// "大牛"
// ]
// 参数可以使字符串
// commandline:"Hi"
// 参数可以是箭头函数
commandline:()=>"Hi Tim"
}
console.log(options.program)
console.log(options.commandline)
接口封装ajax
// 封装ajax
interface Config{
type:string;
url:string;
data?:string;
dataType:string
}
function Ajax(config:Config):any{
const xhr = new XMLHttpRequest();
// 创建连接
xhr.open(,config.type,config.url);
// 发送请求
xhr.send();
xhr.onreadystatechange = function(){
if(xhr.readyState == 4 && xhr.status == 200){
console.log("成功")
if(config.dataType == "json"){
console.log(JSON.parse(xhr.responseText))
}else{
console.log(xhr.responseText)
}
}
}
}
Ajax({
url:"http://localhost:8080/heroall",
type:"get",
dataType:"json"
})
函数类型接口
函数类型接口:对方法传入的参数以及返回值进行约束
// 函数类型接口
interface encrypt{
// 没有函数体
(Key:string,value:string):string;
}
var md5 = function(Key:string,value:string):string{
return Key + "<--->" + value;
}
console.log(md5("root","root"))
接口继承
接口可以继承另一个接口来扩展自己
// 接口继承 接口可以通过其他接口来扩展自己
interface Andy{
eat():void;
}
interface anfn extends Andy{
work():void;
}
class Program{
age:number;
constructor(age:number){
this.age = age;
}
coding():void{
console.log(this.age + "年龄加载")
}
}
class Aniy extends Program implements anfn{
name:string;
constructor(age:number,name:string){
super(age);
this.name = name;
}
eat():void{
console.log(this.name + "吃东西")
}
work():void{
console.log(this.name + "工作")
}
}
const aniy = new Aniy(20,"小牛");
aniy.coding();
aniy.eat();
aniy.work();
泛型
泛型:软件工程中,我们不仅要创建一致的定义良好的API,同时也要考虑可重用性。 组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型,这在创建大型系统时为你提供了十分灵活的功能。
在像C#和Java这样的语言中,可以使用泛型来创建可重用的组件,一个组件可以支持多种类型的数据。 这样用户就可以以自己的数据类型来使用组件。
通俗理解:泛型就是解决 类 接口 方法的复用性、以及对不特定数据类型的支持(类型校验)
泛型函数
// 泛型拯救了 any 泛型可以支持不特定的数据类型
// T 代表泛型
function getDatas<T>(value:T):T{
return value;
}
console.log(getDatas<number>(123));
console.log(getDatas<string>("小牛"));
泛型类
// 泛型类
class MinClass<T>{
public list:T[] = [];
add(value:T){
this.list.push(value);
}
min():T{
var minNum = this.list[0];
for(let i=0;i<this.list.length;i++){
if(minNum>this.list[i]){
minNum = this.list[i];
}
}
return minNum;
}
}
// 实例化传入的 number类型决定了 他真正的类型
var m1 = new MinClass<number>();
m1.add(1);
m1.add(2);
m1.add(3);
m1.add(4);
console.log(m1.min())
泛型接口
// 泛型接口
// 函数型接口泛型
interface ConfigFn{
<T>(value:T):T;
}
var getFn:ConfigFn = function<T>(value:T):T{
return value;
}
getFn<number>(1);
// 泛型接口
interface getData2<T>{
(value:T):T;
}
var getData2 = function<T>(value:T):T{
return value;
}
getData2<string>("小牛");
装饰器
装饰器是一种特殊类型的声明,它能够被附加到类,方法,属性或参数上,可以修改类的行为,通俗的讲装饰器就是一个方法,可以注入到类,方法,性或参数上来扩展类、方法,属性或参数的功能。常见的装饰器有:类装饰器,方法装饰器,属性装饰器,参数装饰器。
装饰器的写法:普通装饰器(无法传参),装饰器工厂(可传参),装饰器是过去几年中JS最大的成就之一,已是ES7的标准特性之一
类装饰器
类装饰器:普通装饰器(无法传参)
// 类装饰器 : 普通装饰器 (不能传参)
function logClass(params:any){
console.log(params); // params 代表当前类
params.prototype.name = "普通装饰器的属性";
params.prototype.run = function(){
console.log("普通装饰器原型动态添加方法")
}
}
@logClass
class HttpClient{
}
const http:any = new HttpClient();
console.log(http.name);
http.run();
装饰器:工厂装饰器(可传参)
// 类装饰器:工厂装饰器(可以传参)
function logClass(param:string){
return function(target:any){
console.log(target) // target 当前类
console.log(param) // param 当前类传进来的参数
target.prototype.url = param;
}
}
@logClass("http:www.xiaoniuniu.com")
class HttpClient{
}
var httpClient:any = new HttpClient();
console.log(httpClient.url);
属性装饰器
属性装饰器会被应用到属性描述上,可以用来监视,修改或替换属性的内容
属性装饰器会在运行时传入两个参数
1.对于静态成员来说是类的构造函数,对于实例来说是类的原型对象
2.成员的名字
// 属性装饰器
function logProperty(params:any){ // params就是当前类传递进来的参数
return function(target:any,attr:any){
console.log(target)
console.log(params)
target[attr] = params;
}
}
class HttpClient{
@logProperty("http:www.niuxiaoniu.com")
public url :any | undefined;
getData(){
console.log(this.url);
}
}
var http = new HttpClient()
console.log(http.url)
方法装饰器
方法装饰器会被应用到方法描述上,可以用来监视、修改或者替换方法定义
方法装饰器会在运行时传入下列3个参数
1.对于静态成员来说是类的构造函数,对于实例成员是类的原型对象
2.成员的名字
3.成员的属性描述符
function get(param:any){
return function(target:any,methodName:any,desc:any){
console.log(target)
console.log(methodName)
console.log(desc)
target.urlAPI = param;
target.run = function(){
console.log("方法装饰器")
}
}
}
class HttpClient{
url : any | undefined;
constructor(){
}
@get("http://www.niuxiaoniu.com")
getData(){
console.log(this.url)
}
}
const http:any = new HttpClient();
console.log(http.urlAPI)
方法参数装饰器
参数装饰器表达式会在运行时当作函数被调用,可以使用参数装饰器为类的原型增加一些元素数据 ,传入下列3个参数:
1.对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
2.方法的名字。
3.参数在函数参数列表中的索引。
function logParam(param:any){
return function(target:any,methodName:any,paramIndex:any){
console.log(target)
console.log(methodName)
console.log(paramIndex)
target.urlAPI = param;
}
}
class HttpClient{
getData(@logParam("123456") uuid:any){
console.log(uuid);
}
}
const http:any = new HttpClient();
http.getData(123456);
console.log(http.urlAPI)
装饰器执行顺序
装饰器执行顺序 : 属性装饰器 ————> 方法装饰器 ————> 方法参数装饰器 ————> 类装饰器
模块化
模块化是将一个大的程序,拆分成多个小文件,然后将小文件组合起来
模块化优点:
- 防止命名冲突
- 代码复用性
- 高维护性
模块化主要由 import 和 export 构成
- export 模块对外暴露
- import 引入暴露的模块
export
单个暴露
// 单独暴露 在需要暴露的内容前面加入 export关键字
export let school = "我爱学习";
export function getData(){
console.log("我可以改变你")
}
统一暴露
let msg = "嘿嘿";
function getMsg(){
console.log("哈哈")
}
export {msg , getMsg};
默认暴露
// 默认暴露 以对象形式暴露
export default{
name:"Hello",
show(){
console.log("Hello Show");
}
}
Import
默认引入
// 引入 将暴露的内容全部引入 并赋值给m1
import * as m1 from "./export";
解构赋值引入
// 解构赋值形式引入
import {msg,getMsg} from "./export2";
针对于默认暴露引入
import m2 from "./export3";
命名空间
命名空间:在代码量较大的情况下,为了避免各种变量命名相冲突,可将相似功能的函数、类、接口等放置到命名空间内,同Java的包,TypeScript的命名空间可以将代码包裹起来,只对外暴露需要在外部访问的对象,命名空间内的对象通过export关键字对外暴露
命名空间和模块的区别:
- 命名空间:内部模块,主要用于组织代码,避免命名冲突。
- 模块:ts的外部模块的简称,侧重代码的复用,一个模块里可能会有多个命名空间
namespace A{
interface Animal {
name: string;
eat(): void;
}
export class Dog implements Animal {
name: string;
constructor(name: string) {
this.name = name;
}
eat(): void {
console.log(`${this.name} ---- 吃骨头!!!`);
}
}
export class Cat implements Animal {
name: string;
constructor(name: string) {
this.name = name;
}
eat(): void {
console.log(`${this.name} ----吃猫粮!!!`);
}
}
}
const aDog = new A.Dog("小狗狗");
aDog.eat();
const aCat = new A.Cat("小喵喵");
aCat.eat();