第一章:Typescript概述
1.TS介绍
1.Typescript是以JavaScript为基础构建的语言,Typescript扩展了JavaScript并添加了类型,可以在任何支持JavaScript的平台中执行,TS不能被js解析器直接执行,因此要把ts转换为js代码来执行
2.ts增加了类型,面向对象的
ts开发环境搭建:下载node.js 安装node.js 进入命令行 输入 npm i-g typescript 创建一个ts文件 使用tsc对ts进行编译
2.基本类型:类型声明
let a:number;//这个声明了一个变量a,同时指定他的类型为number
//因为a的类型设置为了number 在以后的使用过程a的值只能是数字
a=10;
// a='hello';//这个就是报错,因为类型不匹配
console.log(a);
let b:String;
b='计算机科学与技术';
console.log(b);
//如果变量的声明和赋值是同时进行的,ts可以自动对变量进行类型检测
function sum(x :number,y:number) {
return x+y;
}
function sum1(x :number,y:number):number {//声明了函数返回值类型
return x+y;
}
console.log(sum(1, 23));
//使用字面量来进行类型声明
let a:10;
a=10;
//也可以使用 | 或来连接多个字符、
let b: boolean|string;//这个语句读作b的类型可以是布尔值也可以是字符串
b=true;
b='计算机科学与技术';
//any 任何类型,任意赋值,一个类型设置为any后相当于对变量关闭了ts的类型检测 不建议使用
let d:any;
//也就是d变量可以随意赋任意类型的值
d=true;
d='计算机科学与技术';
d=2;
//声明变量如果不指定类型,则ts解析器会自动判断变量的类型为any
//unknown 表示未知类型的值 这个就是一个类型安全的any
let e:unknown;
e=10;
e='计算机科学与技术';
e=true;
//类型断言 可以用来告诉解析器变量的实际类型
let s;
s=e as string;
//void
function fn() :void{//返回值为空值
return null;
}
//never表示永远不会返回结果
// @ts-ignore
function fn2() :never{
}
2.环境搭建
1.下载node
2.安装node
#3.进入 终端 输入 npm i -g typescript
--npx tsc -v查看版本号 检测安装是否成功
4.创建一个ts文件
5.使用tsc 对文件进行编译
终端在当前文件打开输入:----node 文件名
3.TS中的类型声明
let a;
a=10;
// a="hello" 这个代码会报错 原因就类型不匹配
console.log(a)
let b:string;//把b的类型变为字符串
b="计算机科学与技术学院"
console.log(b);
//声明变量追进行赋值
let c: boolean=false;
console.log(c);
//如果变量的声明和赋值是同时进行的 ts可以自动对变量进行类型检测
//js中的函数是不考虑参数的类型和个数的
function fn(a,b){
return a+b;
}
console.log(fn(12, 34));
function sum(a:number,b:number){
return a+b;
}
console.log(sum(123, 223));
//还可以指定 函数的返回值
function f(a:number,b:number):number {//指定函数的返回值为number
return a+b;
}
console.log(f(123, 456));
3.TS的类型声明-1
let a:string
//直接使用字面量进行类型声明
let b:10;
b=10;//这个不报错
// b=11 这个就是报错 原因就是已经定义过了
//可以使用|来连接两个数类型
let c:"male" | "female";
c="male"
c="female"
let d:boolean|string//这个就是限制d的类型是布尔或者字符
//any 表表示任意类型 一个变量设置类型为any相对于对该变量关闭了ts的类型检测
let y:any
//在使用ts时 不建议使用any类
y='哈哈哈'
//声明变量如果不指定类型 则ts解析器会自动判断变量类型为any (隐式的any)
//未定义类型
let e:unknown;
e=10
//unknown时候收纳盒就是一个类型安全的any
//unknown类型的变量 不能追赋值给其他变量
//类型断言 高速编译器 e就是字符串 直接强行赋值
d=e as string
d=<string>e//两种写法完全等价
/*
* void用来表示 以函数为例 就表示没有返回值的函数
*
* */
function fn1():void{//这个就是设置了函数的返回值为空 没有返回值
}
//never 表示永远不会有结果
function fu2():never{
throw new Error("报错了??")//有这种情况用never就可以
}
4.TS的类型声明-2
//object 表示一个对象
let a:object;
a={};
a=function fn() {
console.log("对象")
}
//{}用来指定对象中可以包含那些属性
let b:{name:string};//这个对象可以指定属性
b={name:'吴邪'}
console.log(b);
//在属性后面加上 一个? 代表属性是可选的
let c:{name:string,age?:number,[proName:string]:any}
//[proName:string] any 表示任意类型的属性
/*
* 设置函数结构的类型声明:
* 语法:(形参:类型,形参:类型...)=>返回值
*
* */
let d:(a:number,b:number)=>number
d=function g(n1,n2){
return n1+n2
}
console.log(d(12,67))
//string[] 表示字符串类型
let e:string[]
e=['a','b','c']
//number[] 表示数值数值
let f:number[];
let g:Array<number>;
/*
* 数组的类型声明:
* --类型[]
*
* 元组:就是固定长度的数组
* 语法:[类型,类型 ,类型]
* */
let h:[string,string];
h=['hello','计算机'
]
console.log(h);
/*
* 枚举
* enum
* */
let i:{name:string,gender:string};
i={
name:'孙悟空',
gender:'男'
}
console.log(i.name)
//定义枚举:
enum Gender{
Male,
Femle,
}
let j:{name:string,gender:Gender};
j={
name:'吴邪',
gender:Gender.Femle
}
console.log(j.gender===Gender.Femle)
//&表示且 这样子是没有意义的
let k:{name:string}&{number:number};
//类型的别名
type myType=string
let o:1|2|3|4|5
let l:1|2|3|4|5
let m:myType//起名来代替
5.TS编译选项-1
console.log("hello")
//在终端编译ts的时候 可以这样子 tsc 文件.ts -w 就可以自动编译
let a=10
var c="计算机科学"
console.log(c);
let obj:{
name:'吴邪',
age:19
}
console.log(obj.age)
//终端输入 tsc 直接就可以把全部ts文件编译 但是要完成这个操作 需要建立一个ts的配置文件
{
/*
tsconfig.js是ts编译器的配置文件 ts编译器可以根据它的信息来对代码进行编译
-- "include": []用来绝对那些ts文件需要编译 /**表示任意目录
* 表示任意文件
*/
"include": [
"./src/**/*"
],
// 这个是可选的
"exclude": [
"./src/hello/**/*"//表示被排除的文件 不需要被编译的文件目录
],
"extends": ""//表示继承那个文件
}
6.TS编译选项-2
{
/*
tsconfig.js是ts编译器的配置文件 ts编译器可以根据它的信息来对代码进行编译
-- "include": []用来绝对那些ts文件需要编译 /**表示任意目录
* 表示任意文件
*/
"include": [
"./src/**/*"
],
/*
"compilerOptions": {} 编译器的选项
*/
"compilerOptions": {
"target": "ES2020",//用来指定ts被编译为es的版本
"module": "ES2020",//module指定使用的模块化规范
"lib": ["dom"],//指定需要使用的库 一般不需要去设置
"outDir": "",//用来指定编译后文件所在目录 前提是要文件目录存在
// 文件输出目录
"outFile": "",//将代码合并为一个文件 设置outFile后 所有的全局作用域中的代码会合并到同一个文件中
"allowJs": false,//是否对js文件进行编译 默认不编译
"checkJs": false,//是否检查的js是否符合语法规范
"removeComments": false,//是否移除注释 true 是 FALSE 否
"noEmit": false,//不生成编译后文件
"noEmitOnError": false,//当有错误时 不生成编译后的文件
}
}
7.TS编译选项-3
{
/*
tsconfig.js是ts编译器的配置文件 ts编译器可以根据它的信息来对代码进行编译
-- "include": []用来绝对那些ts文件需要编译 /**表示任意目录
* 表示任意文件
*/
"include": [
"./src/**/*"
],
/*
"compilerOptions": {} 编译器的选项
*/
"compilerOptions": {
"target": "ES2020",//用来指定ts被编译为es的版本
"module": "ES2020",//module指定使用的模块化规范
"lib": ["dom"],//指定需要使用的库 一般不需要去设置
"outDir": "",//用来指定编译后文件所在目录 前提是要文件目录存在
// 文件输出目录
"outFile": "",//将代码合并为一个文件 设置outFile后 所有的全局作用域中的代码会合并到同一个文件中
"allowJs": false,//是否对js文件进行编译 默认不编译
"checkJs": false,//是否检查的js是否符合语法规范
"removeComments": false,//是否移除注释 true 是 FALSE 否
"noEmit": false,//不生成编译后文件
"noEmitOnError": false,//当有错误时 不生成编译后的文件
"alwaysStrict": false,//用来设置编译后文件是否使用严格模式 默认为false
"noImplicitAny": false,//不允许隐式的Any类型
"noImplicitThis": false,//检查隐式的this
"strictNullChecks": false,//非空检测
"strict": false,//严格检查的总开关 只要一设置true所有检查都会打开
}
}
8.使用Webpack打包代码
1.终端输入:npm init -y
在输入:npm i -D 安装开发依赖
在输入:npm i -D webpack webpack-cli typescript ts-loader 安装好依赖之后
//1.先引入一个包
const path=require('path')
module.exports={
// 在webpack中的配置信息都应该写在这里
// 指定入口文件
entry: "./src/index.ts",
// 指定打包文件位置
output:{
// 指定打包后的文件目录
path:path.resolve(__dirname,'dist'),
// 指定打包后文件名字
filename:"bundle.js"
},
// 指定Webpack打包时 使用的模块
module:{
// 指定要加载的规则
rules:[
{
//这个指定是规则生效的文件
test:/\.ts$/,
//要使用的loader
use:'ts-loader',
// 要排除的文件夹
exclude:/node-modules/
}
]
}
}
{
"name": "pro-3",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build":"webpack"//书写这个 构建代码
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"ts-loader": "^9.4.2",
"typescript": "^4.9.4",
"webpack": "^5.75.0",
"webpack-cli": "^5.0.1"
}
}
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"sourceMap": true
},
"exclude": [
"node_modules"
]
}
终端输入npm run build运行
9.Webpack打包代码-2
安装Webpack插件:
终端输入:npm i -D html-webpack-plugin
//1.先引入一个包
const path=require('path')
//2.引入html-Webpack插件
const HTMLWebpackPlugin=require('html-webpack-plugin')
module.exports={
// 在webpack中的配置信息都应该写在这里
// 指定入口文件
entry: "./src/index.ts",
// 指定打包文件位置
output:{
// 指定打包后的文件目录
path:path.resolve(__dirname,'dist'),
// 指定打包后文件名字
filename:"bundle.js"
},
// 指定Webpack打包时 使用的模块
module:{
// 指定要加载的规则
rules:[
{
//这个指定是规则生效的文件
test:/\.ts$/,
//要使用的loader
use:'ts-loader',
// 要排除的文件夹
exclude:/node-modules/
}
],
},
plugin: [
//配置完毕后 自动生成html文件
new HTMLWebpackPlugin(),
]
}
插件: npm i -D clean-webpack-plugin 可以做到实时更新最新文件
10.Webpack打包代码-3
终端输入:
npm i -D @babel/core @babel/preset-env babel-loader core-js
第二章:面向对象
1.面向对象介绍
//1.使用class关键字定义一个类
/* 对象中主要包含两个部分:
* 属性
* 方法
*
*
*
* */
class Person{
name:string ='吴邪';
gender:string='男';
age:number=19
static sys :string='安卓系统'
readonly address:string='吴山居';//以readonly开头的属性是只读属性 不能修改
}
const per=new Person();
console.log(per.name,per.age)
/* 对定义的属性是实例属性 需要通过对象的实例去访问
const per=new Person()
per.name
使用static开头的属性是静态属性(类属性) 可以直接通过类对象去访问
*
* */
//:类属性 或者静态属性
console.log(Person.sys)
per.name='王胖子';
/*
* 定义方法:
* 如果在方法前面使用static关键字开头就是静态方法 可以通过类名直接调用
* */
class hero{
test(){
console.log("你好!")
}
}
2.构造函数和this
class Person{
name='吴邪';
age=90
bark(){
alert("你好 计算机科学与技术学院")
}
}
const t=new Person();
console.log(t.name);
//对象:t
console.log(t);
class Person2{
name:string;
age:number;
// 构造函数会在对象创建的时候调用
constructor(name:string,age:number) {
//在实例方法中 this就表示当前的实例 在构造函数中当前对象就是当前新建的那个对象
//在构造函数可以通过this向新建对象中添加属性
this.name=name;
this.age=age;
}
bark(){
//在方法中可以通过this来表示当前调用方法的对象
console.log(this.name)
}
}
const x=new Person2("吴邪",45);
console.log(x);
console.log(x.bark());
3.继承简介
//定义一个类
class Dog{
name:string;
age:number
constructor(name:string,age:number) {
this.name=name;
this.age=age;
}
sayHello(){
console.log("旺财!")
}
}
const dog=new Dog("旺财",19);
dog.sayHello()
console.log(dog);
//定义一只猫咪
class Cat{
name:string;
age:number;
constructor(name:string,age:number) {
this.name=name;
this.age=age;
}
sayHello(){
console.log("喵喵")
}
}
const cat=new Cat("咪咪",90)
cat.sayHello()
console.log(cat);
//定义一个Animal类 为父类
class Animal{
name:string;age:number;
constructor(name:string,age:number) {
this.name=name;
this.age=age;
}
//动物的行为定义为参数
sayHello(behavior:string){
console.log(behavior)
}
}
//定义一个子类
class Cat2 extends Animal{
// 使Cat2类继承Animal类
// 在这种情况下 Cat2继承了Animal的所有属性和方法
// 这样只需要写一次 这样子就可以使各个子类同时拥有父类中的所有方法和属性
// 如果希望在子类中添加一些父类中没有的属性和方法
run(){
console.log("跑起来了")
}
}
let cat2 = new Cat2("小猫",12);
cat2.sayHello('喵喵')
cat2.run()
class Dog2 extends Cat2{
// 可以反复套娃 无限下去
// z注意:如果在子类中添加了和父类相同的方法 则子类方法会覆盖掉父类的方法 这种形式称为方法的重写
sayHello(behavior: string) {
super.sayHello(behavior);
console.log("旺旺")
}
}
4.super关键字
class Animal{
name:string;
constructor(name:string) {
this.name=name
};
sayHello(){
console.log("大家好!")
}
}
//继承这个类
class Dog extends Animal{
sayHello() {
super.sayHello();//表示父类 在类的方法中 super就表示当前类的父类
}
}
let dog = new Dog("吴邪");
dog.sayHello();
console.log(dog);
class DogTest extends Animal{
// 如果在子类写了构造函数 在子类构造函数中必须得调用一些父类的构造函数
age:number;
constructor(name:string,age:number) {
super(name);//调用父类的构造函数
this.age=age;
}
}
5.抽象类
/*
* 以abstract开头的类为抽象类
* 抽象类和其他类区别不大 只是不能用来创建对象
抽象类就是用来专门被继承的类*
*
* 当我们不希望用这个类来创建对象的时候 可以使用这个关键字来创建类
*
* 注意:在抽象类中可以添加抽象方法
*
* */
abstract class Animal {
name: string;
sayHello() {
console.log("你好!")
};
// 定义抽象方法 abstract +方法名(){}
// 抽象方法只能定义在抽象类中 注意抽象方法没有方法体 子类必须对抽象方法进行重写
abstract MyDay():void;
}
//这个类只可以继承 不可以实例化
class Cat extends Animal{
MyDay() {
// 重写了这个方法 就不会报错了
console.log("你好")
}
}
console.log(Cat);
let cat = new Cat();
console.log(cat.MyDay());
6.接口
//想去描述对象的类型
type myType={
name:string,
age:number
}
const obj:myType={
name:'吴邪',
age:11
}
//因此我们使用接口:
/*
* 接口:接口就是用来定义一个类结构 用来定义一个类中应该包含那些属性和方法
* 同时接口也可以当成类型声明去使用
*
*
*
* */
interface MyInterface{
name:string,
age:number
}
interface MyInterface{
gender:'男'
}
//使用接口
const x:MyInterface={
name:'吴邪',
age:19,
gender:'男'
}
/*接口可以在定义类的时候去限制类的结构:
* 接口中的所有属性都不能有实际的值 接口只定义对象的结构 而不能考虑实际值 在接口中所有的方法都是抽象方法
*
* */
//定义类时 可以使类去实现一个接口 实现接口就是使类去满足接口的要求
class MyClass implements MyInterface{
name:'王胖子'
age:19
gender:'男'
}
7.属性的封装
第19节课