学习鸿蒙之前的准备工作之回顾TypeScript
鸿蒙开发大部分开发是移动设备的,但是移动端的开发也可以使用网页开发的技术去实现,但是需要三种基础,分别是HTML,CSS,JavaScript等,写出来的话,过于繁琐(当然也可以使用其他的前端框架),避免这些繁琐的内容,可以依靠ArkTs
什么是ArkTs?
ArkTS是HarmonyOS优选的主力应用开发语言。ArkTS围绕应用开发在TypeScript(简称TS)生态基础上做了进一步扩展,继承了TS的所有特性,是TS的超集。

什么是TypeScript
JavaScript:动态类型语⾔(Dynamically Typed Language),在运⾏期间检查数据的类型的
语⾔。⽤这类语⾔编程,不会给变量指定类型,⽽是在赋值时得到数据类型。
TypeScript是微软开发的⼀个开源的编程语⾔,通过在JavaScript的基础上添加静态类型定义构
建而成
TypeScript增加了什么?
● 类型
● 完美⽀持ES新特性
● 添加ES不具备的新特性
● 丰富的配置选项
● 强⼤的开发⼯具
全局安装TS
1.进⼊DOS界⾯
2.输⼊:npm i -g typescript
3.验证:tsc -v
将ts⽂件编译成js⽂件 tsc test.ts
// 案例一:
var a = 123
a='yuanzi'
a=true
// 案例二:
funcation fn(){
console.log(1)
}
TypeScript中简单的数据类型
类型声明 [变量名:类型]
- 类型声明是TS中⾮常重要的特点
- 通过类型声明可以指定TS中变量(形参)的类型
- 指定类型后,当变量赋值时,TS编译器就会⾃动检查值是否符合声明类型,如果符合就赋值,不符合就报错
- 简单的说,类型声明就是给变量设置了类型。使得变量只能存储某种类型的值。
- 变量类型 :number boolean array string object
语法:
// 类型声明:
// let 变量名:类型;//只声明,未赋值
// let 变量名:类型=值;//声明并赋值
// function fun(参数:类型,参数:类型):类型{
// }
//变量类型 number boolean array string object
let b:number;//声明了变量b,指定了类型
b=123;//给b赋值123
// b='yuanzi'; //因为给了他number类型,b赋值了之后不能再赋值其他类型了
// 声明并赋值
let c:boolean=true;
// 形参声明类型
function fun(name:string){
console.log(name);
}
// fun(123);
console.log(b+'=b');
console.log(c+'=c');
fun('yuanzi');
自动类型判断
- TS拥有⾃动类型判断机制
- 当对变量的声明和赋值同时进⾏时,TS编译器会⾃动判断变量类型
- 所以如果你的变量的声明和赋值是同时进⾏的,可以省略掉类型声明
let a:number=123;
//这个说明给这个b设置了number这个类型
let b=23;
// b='yuanzi';//因为是字符串,类型定义的是number类型,赋值的话就会报错
console.log(typeof a);
console.log(typeof b);
字面量
字⾯量:是个客观存在⽆法改变的值。例如: 1 2 3 4 5 6 true ‘hello’
//使⽤字⾯量声明后a的值,永远是12 相当于常量不能修改
let c:12;
// c=13;
const b=12;
any
any:表示任意数据类型,⼀个变量设置类型为any后相当于对该变量关闭了TS的类型检测
使用any存在的隐患:
- 使用any声明的变量不仅会影响到自己也会影响到别人
- 不同类型的变量值赋值之后,也会改变被赋值的变量类型
let a:any;//显式的any类型声明
a=123;
a='yuanzi';
a=true;
let b;//隐式的any 如果不设定类型,自动判断该变量的类型是any
b=123;
b=true;
b='yuanzi';
let c:number;
c=12;
c=b;
console.log(typeof a);//any
console.log(typeof b);//any
console.log(typeof c);//any
TS的unknow(安全的any)
let a:unknown;
a=123;
a='yuanzi';
a=true;//只会打印出最后一个
let b:boolean;
//这个时候我想赋值给b,如下
// b=a;
// 此时ts解析会报错,
// 虽然a b变量中的字面量都是string
// 但是a 是string类型 b是unknown类型 所以不能赋值
//也可以使用这种办法
if(typeof a ==='boolean'){
b=a;//直接可以赋值了
}
console.log(a);//true
console.log(b);//true
TS的类型断言
类型断⾔:可以⽤来告诉TS解析器变量的实际类型
语法:<font style="color:rgb(0,0,0);">变量 as 类型</font>
let a:unknown;
a=123;
let b:number;
// 可以处理上一个问题
if(typeof a ==='boolean'){
b=a;//直接可以赋值了
}
// 可以利用类型断言来处理解决unknow赋值问题
b= a as number;
TS的函数
对函数中形参进⾏类型声明,
- 按照函数声明的形参类型传递参数
- 形参和实参数量一致
function fun(形参1:number,形参2:number){
console.log(形参1+形参2);
}
//调⽤
//传递不是number的实参
//TS解析器提示报错,不允许这样做,我们必须按照函数声明的形参类型传递参数
fun('yuanzi','net');
fun(123,456);//正确的参数
fun(123,4556,55,56);//多参数 TS解析器报错
fun(11);//少参数 TS解析器报错
//对函数中形参进行类型声明
function fun1(age:number){
console.log(age);
}
fun1(18);
function fun2():string{
return "123";
}
let a=fun2();
console.log("a="+ typeof a);
函数中返回值类型的声明
第⼀种情况:不设置返回值类型,但是有返回值(undefined)
// 不设置返回值类型,但是有返回值 undefined
function fun2(){}
let a = fun2();
//这个时候ts解析器会根据返回值的类型进行判断,返回值的类型是什么函数返回值类型就是什么
console.log("a="+ typeof a);
第二种情况:设置返回值类型为void(用来表示空,以函数为例,就表示没有返回值的函数)
- 不能传递字符,字符串,对象,数组,或者布尔值
function fun3():void{
// return 'a';//报错
// return 112;//报错
// retrun 'yuanzi';//报错
// return true;//报错
// return NaN;//报错
return null; //ok 可以返回
return undefined;// ok 可以返回
// return ;
}
第三种情况:设置返回值类型为never(永远不会返回结果)
function fun4():never{
//程序报错代码立马结束,立即结束以后就不会返回值了
throw new Error("提示信息!!");
}
let d=fun4();
console.log("d="+d);

TypeScript中复杂的数据类型声明
对象的类型声明
object表示⼀个对象
//声明一个变量,类型为Object,相当于a用来保存一个对象
let a:object;
a={};
a=function(){};
//这2个没有限制,而且不实⽤,因为在js中对象太多了,⼀切皆为对象。
这样写表示声明⼀个变量b 类型为对象,对象中只能有⼀个属性为名为name且属性值的类型为string
let b:{name:string};
b={name:'yuanzi'};
b={}//提示报错
b={name:'yuanzi'}
用来指定对象中可以包含哪些属性 严格按照指定对象的格式
需求一:我们指定的对象它必须包含一个name,但是还有age和sex这个俩个变量是可能有可能有没有的,这种情况我们该怎样做呢?
可以使用 属性?:类型
let c:{
name:string,
age?:number,
sex?:string
}
c={
name:'yuanzi',
age:18
}
需求二:当我们只知道我们必须有的属性,而其他的不必须我们不知道,我们该怎么处理呢?
可以通过以下方式实现,指定b中的存储类型是对象,并且这个对象必须含有一个name的属性,类型为string,这个对象还可以有其他可选属性,只要属性名满足字符串,属性值是unknown即可
let b:{name:string, [propName : string] : unknown}
// let propName:string;
// propName='yuanzi';
// propName='园子';
//这个任意命名,表示属性的名字,这个属性名字的类型是string,js中属性名一般都是用string定义
//[propName:string]
let d:{
name:string,
//合起来代表属性名为string类型,且可选的并且这个属性的值为unknown类型
[propName:string]:unknown
}
d={
name:'yaunzi',
sayHello(){
console.log(this.name);
}
}
console.log(d.name);
if (typeof d.sayHello === 'function'){
d.sayHello();
}
数组类型声明
数组类型声明的语法
第一种: let 变量名:类型名[ ]
第二种: let b:变量名<类型名>;
//声明一个数组 string[]表示字符串数组 所以里面只能是字符串
let a:string[];
a[0]='yuanzi';
// a[1]=true;//报错
//类型声明只能是boolean
let b:Array<boolean>;
b[0]=false;
// b[0]='yuanzi';//报错
// 如果想要创建一个任意类型的数组
let e:Array<any>
let e:any[]
扩展类型tuple
tuple:叫做元组
语法:[类型,类型, 类型]
元组 : 定⻓的数组
(就代表数组中的数量是固定的就叫做元组,元组的存储效率⽐较好点,因为元组是固定,不会出现扩容的现象,所有效率会好点)
// 扩展类型tuple(元祖 定长的数组 固定的)
//定义一个元祖,必须按照声明的结构定义数组,不然解析器会提示报错
let a:[string,boolean,number];
a=['yuanzi',true,123];
console.log(a);//'yuanzi',true,123
TS中Enum
enum(枚举): 一个特殊的对象
在数学和计算机科学理论中,⼀个集的枚举是列出某些有穷序列集的所有成员的程序,或者是⼀种特定类型对象的计数
TS中的枚举Enum:定义⼀些带名字的常量。⽤于清晰地表达意图或创建⼀组有区别的⽤例
语法: enum 枚举名称{成员1,成员2…};
//数字枚举
enum a{
//
male=0,
female
};
console.log(a.male);
console.log(a.female);//刚开始定义的时候并没有赋值,他会自动加一
//字符串枚举
enum b{
red='红',
yellow='黄',
blue='蓝'
}
console.log(b.red);
console.log(b.yellow);
console.log(b.blue);
TS中的联合类型声明
使⽤“|” 进⾏联合类型声明
语法:let 变量名:变量类型1|变量类型2;
let a:number|string;
a=123;
a='yuanzi';
//限制b的范围,b只能是12 13 14 15 如果是其它的报错
let b:12|13|14|15;
b=12;
b=15;
// b=16;//报错
TS中类型别名
简化我们书写的代码
语法: type 类型别名的名字 = 声明类型别名
// 如果变量a b的取值范围是一样的,如果还有其他十几个变量的取值范围也是一样的,怎么办
// let a:1|2|3|4|5|6|7|8|9|10;
// let b:1|2|3|4|5|6|7|8|9|10;
type myType=1|2|3|4|5|6|7|8|9|10;
// 使用类型别名来优化
let a:myType;
let b:myType;
a=1;
b=2;
console.log(typeof a);
console.log(typeof b);
TypeScript的配置
如何开启⾃动编译ts⽂件的功能
⾃动编译单个⽂件
编译⽂件时,使⽤-w指令后,TS编译器会⾃动监视⽂件的变化,并在⽂件发⽣改变时对⽂件进⾏重新编译。
tsc 文件名.ts -w
⾃动编译当前项⽬下的所有的ts⽂件
- 如果直接使⽤tsc指令,则可以⾃动将当前项⽬下的所有的ts⽂件编译成js⽂件
- 有⼀个前提,⾸先在项⽬的根⽬录下创建⼀个ts的配置⽂件 tsconfig.json
- tsconfig.json是⼀个json⽂件,添加配置后,只需要tsc命令即可完成对整个项⽬的编译
1.创建一个ts的配置文件 tsconfig.json
2.使用tsc命令
详解tsconfig.json中的配置选项
// tsconfig.json
{
// "include": ["./dev"],
// "exclude": ["./prop/**/*"]
// "extends": "./config/base"
// "files": ["./dev/devDemo.ts"]
// "compilerOptions": {
// "target": "ES6",
// "module": "amd",
// "lib": ["DOM"]
// "outDir": "./dist",
// "outFile": "./dist/app.js",
// "allowJs": true,
// "checkJs": true
// "removeComments": true,
// "noEmit": true,
// "noEmitOnError": true,
// "alwaysStrict":true
// "noImplicitAny":true,
// "strictNullChecks":true
// "strict": true
}
}
include
定义希望被编译⽂件所有的⽬录(更目录(tsconfig.json所在的目录)所有的ts文件都会被编译)
默认值:[/]
"include":["dev/**/*","prop/**/*"]
// **:表示任意⽬录
// *:表示任意⽂件
//就代表所有的dev⽬录和prop⽬录下的⽂件都会被编译
exclude
定义不需要编译的⽬录
// 默认值:
["node_modules","bower_components","jspm_packages"]
// 案例:
"exclude":["./prop/**/*"]
//代表不编译prop⽬录下的所有⽂件
extends:
定义被继承的配置⽂件
"extends":"./config/base"
//表示当前配置⽂件会⾃动包含config⽬录下base.json中的所有配置信息
files:
指定需要编译⽂件的列表(很少使用,一般用在文件毕竟较少的时候)
"files":[
"one.ts",
"two.ts",
"three.ts",
"four.ts"
]
// 表示列表中⽂件都会被TS编译器编译
complierOptions :
ts编译时的配置
详解tsconfig.json中的complierOptions
- target:指定ts编译的js⽬标版本
// 可选值:"ES3"(默认), "ES5", "ES6"/ "ES2015", "ES2016", "ES2017"或 "ESNext"。
// 案例:
"compilerOptions":{
"target":"ES6"
}
//表示我们所编写的ts代码将会被编译ES6版本的js代码
- module:指定使⽤的模块化规范:
// 可选值:
// "None", "CommonJS", "AMD", "System", "UMD", "ES6"或 "ES2015"。
// ▶ 只有 "AMD"和 "System"能和 --outFile⼀起使⽤。
// ▶ "ES6"和 "ES2015"可使⽤在⽬标输出为 "ES5"或更低的情况下。
- lib:指定编译过程中需要引⼊的库⽂件的列表
// 可选值
// ▶ ES5
// ▶ ES6
// ▶ ES2015
// ▶ ES7
// ▶ ES2016
// ▶ ES2017
// ▶ ES2018
// ▶ ESNext
// ▶ DOM
// ▶ DOM.Iterable
// ▶ WebWorker
// ▶ ScriptHost
// ▶ ES2015.Core
// ▶ ES2015.Collection
// ▶ ES2015.Generator
// ▶ ES2015.Iterable
// ▶ ES2015.Promise
// ▶ ES2015.Proxy
// ▶ ES2015.Reflect
// ▶ ES2015.Symbol
// ▶ ES2015.Symbol.WellKnown
// ▶ ES2016.Array.Include
// ▶ ES2017.object
// ▶ ES2017.Intl
// ▶ ES2017.SharedMemory
// ▶ ES2017.String
// ▶ ES2017.TypedArrays
// ▶ ES2018.Intl
// ▶ ES2018.Promise
// ▶ ES2018.RegExp
// ▶ ESNext.AsyncIterable
// ▶ ESNext.Array
// ▶ ESNext.Intl
// ▶ ESNext.Symbol
// 案例:
// "compilerOptions":{
// "target":"ES6",
// "lib":["ES6","DOM"]
// }
// 注意:如果--lib没有指定默认注⼊的库的列表。默认注⼊的库为:
// ▶ 针对于--target ES5:DOM,ES5,ScriptHost
// ▶ 针对于--target ES6:DOM,ES6,DOM.Iterable,ScriptHost
outDir:⽤来指定编译后⽂件所在的⽬录
// 案例:
// "compilerOptions":{
// "target":"ES6",
// "lib":["ES6","DOM"],
// "outDir":'./dist'
// }
outFile:将编译的代码合并成⼀个⽂件
// 案例:
// "compilerOptions":{
// "target":"ES6",
// "lib":["ES6","DOM"],
// "outDir":'./dist',
// "outFile":'./dist/main.js'
// }
// "outFile":'./dist/main.js'
// //就表示把编译后的⽂件合并的main.js这⽂件中,最后只会输出⼀个js⽂件
// 出现问题的解决⽅案:
// mudule只能使⽤ amd或者是system
// 其实outFile这个功能我们在⼯作中也很少使⽤,
// 因为我们打包的时候都是通过打包⼯具进⾏使⽤的。
// 所以这个outFile⼤家知道有这个东⻄了解⼀下就⾏
allowJs :是否对js⽂件进⾏编译
// 默认值:false
// 案例:
// "allowJs":true
checkJs:是否检查js代码符合语法规范
// 默认值:false
// 案例:
// "checkJs":true
removeComments:在编译的时候是否移除注释
// 默认值:false
noEmit:不⽣成编译后的⽂件
// 默认值为:false
// 案例:
// "noEmit":true
// //这个有什么⽤呢,可能有时候你就想⽤ts的语法检测。就可以使⽤这个
noEmitOnError:当存在语法错误的时不⽣成编译后的⽂件
// 默认值:false
// 案例:
// "noEmitOnError":true
alwaysStrict :设置编译后的⽂件是否使⽤严格模式
// js中有⼀种模式叫做严格默认,它语法更严格,在浏览器执⾏的性能更⾼,开发时候我们都会让我们的代码
// 在严格模式下执⾏
// 如果是在js⽂件的话 只需要在js⽂件的开头加⼊⼀个字符串
// "use strict";
// //就表示开启了js的严格模式
// 设置编译后的⽂件是否使⽤严格模式
// 默认值:false
// 案例:
// "alwaysStrict":true
// 当代码中有引⼊导出模块代码时,js会⾃动进⼊严格模式下
noImplicitAny:不允许隐式的any类型
// 默认值为:false
// 案例:
// "noImplicitAny":true
strictNullChecks:严格的检查空值
// 默认值为:false
// 案例:
// "strictNullChecks":false
strict:所有严格检查的总开关
// 默认值为:false
// 案例:
// "strict":false
TypeScript的语法进阶
配置在直接运⾏ts环境
⾸先全局安装ts-node:npm install -g ts-node
执⾏ts-node命令即可: ts-node hello.ts
面向对象简介
⾯向对象编程:程序之中所有操作都需要通过对象来完成

程序中的对象:

js里面的对象:
- 内置对象:方法,数组,集合,字符串,number,布尔型
- 本地对象:window
- 自建对象,自定义对象
TS中的类
既然要⾯向对象,操作对象,⾸先便要拥有对象,那么下⼀个问题就是如何创建⼀个对象?
要创建⼀个对象,必须先定义⼀个类,所谓的类可以理解为对象模型,程序中可以根据类创建指定类型的对象
1、如何定义类
2、静态修饰符(static):static修饰之后只属于class了,不属于实例对象了
3、readonly :被readonly修饰的属性,只能读取不能修改
//通过class这个关键字来定义⼀个类
class Person{
name:string;
age:number;
}
//通过这个类实例化⼀个对象
//let man=new Person();//括号里面没有参数的时候,括号可以省略的
let man=new Person;
man.name="园子";
man.age=30;
console.log(man);
//static
class Animal{
//name被static修饰之后只属于class了,不属于实例对象了
static readonly nameD='猫';// 被readonly修饰的属性,只能读取不能修改
say(){
console.log("动物在叫");
}
}
let dog=new Animal;
// dog.name="狗";
// console.log(dog.name);
dog.say();
// Animal.nameD='狗';
// console.log(Animal.nameD);// Cannot assign to 'nameD' because it is a read-only property.
类中的构造方法
1、如何在类中定义⼀个构造⽅法
// 1):定义⼀个简单的构造⽅法
class Dog{
constructor(){
console.log("我创建⼀个Dog");
}
}
const dog=new Dog();
//当我们调 new Dog();的时候我们就等于调⽤Dog中的构造⽅法
//在实例犯法中,this就表示当前的实例
//在构造⽅法中当前对象及时当前新建的那个对象
//可以通过this向新建的对象中添加属性
// 2):定义⼀个有参构造⽅法
class Dog{
constructor(name:string){
console.log(name);
}
}
const dog=new Dog("⼤⻩");
//创建的时候必须传递⼀个string类型的参数
2、this改造构造⽅法
class Animal{
name:string;
constructor(name:string){
//在实例方法中,this就表示当前的实例
//在构造⽅法中当前对象就是当前新建的那个对象
//可以通过this向新建的对象中添加属性
this.name=name;
}
}
let dog=new Animal("狗");
console.log(dog.name);
继承的简介(extends)

class Animal{
name:string;
sleep(){
console.log(this.name+"在睡觉");
}
// 定义一个构造方法来初始化属性,带入一个形参,对上面的name进行赋值
constructor(name:string){
this.name=name;
}
}
// 继承动物类 此时,Animal被称为⽗类,Dog被称为⼦类
class Dog extends Animal{
hobbit(){
console.log(this.name+"爱吃骨头");
}
}
let jm = new Dog("金毛");
jm.hobbit();
console.log(jm.name);
- 使⽤继承后,⼦类将会拥有⽗类所有的⽅法和属性
- 通过继承可以将多个类中共有的代码写在⼀个⽗类中
- 这样只需要写⼀次即可让所有⼦类都同时拥有⽗类中的属性和⽅法
- 如果希望在⼦类中添加⼀些⽗类中没有的属性或⽅法直接加就⾏
TS中的重写
⼦类覆盖了⽗类中的属性或者是⽅法叫做重写
class Animal{
name:string="动物";
sleep(){
console.log("动物在睡觉");
}
}
// 对name的重写
class Dog extends Animal{
name:string="狗";
sleep(){
console.log("狗在睡觉");
}
}
let jm=new Dog();
console.log(jm.name);
jm.sleep();
super关键字
// super 在当前类中 super就表示当前类的父类 如果有参数的话也需要传递对应的参数
class Animal{
name:string;
sleep(){
console.log(this.name+"在睡觉!!!!");
}
constructor(name:string){
this.name=name;
}
}
class Dog extends Animal{
// 添加一个属性age
age:number;
// 重写sleep方法
sleep(){
//super 代表父类 父类也被成为超类
super.sleep();
}
//在子类中定义构造方法的时候,需要通过这个super调用父类的构造方法,
//因为在子类中定义的构造方法已经把父类的构造方法覆盖了,就不会执行父类的构造方法了
//所以在父类中定义的属性name就没有办法进行初始化的赋值
constructor(name:string,age:number){
super(name);//要写上,否则会覆盖父类的关键字
this.age=age;
}
}
let jm=new Dog("金毛",12);
jm.sleep();
console.log(jm);
抽象类(abstract)
以abstract开头的类被称为抽象类
- 抽象类和其他类区别不⼤,只是不能⽤来创建对象
- 抽象类就是专⻔⽤来被继承的类
- 抽象类中可以添加抽象⽅法
- 抽象⽅法使⽤abstract开头,没有⽅法体
- 抽象⽅法只能定义在抽象类中,⼦类必须对抽象⽅法进⾏重写
abstract syaHello():void; - 抽象类使⽤场景,当你不希望某个类被创建时,可以使⽤抽象类
abstract class Animal{
name:string="抽象类";
// abstract sleep(){}//报错
// 抽象方法特点
// 1:没有方法体,没有实现
abstract sleep():void;
}
// let dog=new Animal();//报错
//1:抽象类只能被继承,不能初始化一个实例
//2:子类继承抽象类,必须重写抽象类中所有抽象方法,如果不重写,那么这个类也应该是一个抽像类
// class Dog extends Animal{//报错
// sleep(){}
// }
//定义一个抽象类不需要重写
abstract class Dogs extends Animal{
abstract bark():void;
}
class JM extends Dog{
// 子类继承抽象类,必须重写抽象类中所有抽象方法
sleep(){}
bark(){};
}
TS中的接口(interface)
回顾:
type myType=string|number;//类型声明
let a:myType;//说明a只能是字符串类型或者是数字类型
a=123;
// a=true;//报错
接⼝:接⼝⽤来定义⼀个类结构,⽤来定义⼀个类中应该包含哪些属性和⽅法。同时接⼝也可以当成类型声明去使⽤。接⼝可以重复声明,取所有相同接⼝名的并集
//interface+接口名字 包含属性和方法
interface myInterface{
name:string;
//1在接口里面的方法都是抽象方法,只有方法名,参数,返回类型,没有返回体的实现
sleep():void;
}
//2.接口可重复声明
interface myInterface{
age:number;
}
// 类型声明
let b:myInterface;
b={
name:'yuanzi',
age:12, // 上面声明了,下面也要写上去
sleep(){
console.log("myInterface");
}
}
console.log(b.name);//yuanzi
b.sleep();//myInterface
// Person这个类继承了myInterface这个接口 就要继承他的属性和方法
//3.通过一个类来实现接口
class Person implements myInterface{
name:string;//必须包含前面定义的
age:number;
gender:string;
sleep(){
console.log(this.name);
}
constructor(name:string,age:number,gender){
this.name=name;
this.age=age;
this.gender=gender;
}
}
let c=new Person('小D',12,'男');
console.log(c);
c.sleep();
快速掌握TS中属性的封装
1、属性修饰符
public: 修饰的属性可以在任意位置访问(修改),是默认值
private: 私有属性,私有属性只能在类内部进⾏访问(修改)-通过在类中添加⽅法使得私有属性可以被 外部访问
protected: 受保护的属性,只能在当前类何当前类的之类中访问(修改)
2、属性封装
class Person {
private name:string;
private age:number;
constructor(name:string,age:number){
this.name=name;
this.age=age;
}
}
3、属性存取器
// getter ⽅法⽤来读取属性
// setter ⽅法⽤来设置属性
// -它们被称为属性存取器
class Person {
private name:string;
private age:number;
constructor(name:string,age:number){
this.name=name;
this.age=age;
}
get name():string{
return this.name;
}
set name(name:string):void{
this.name=name;
}
}
class Person{
name:string;
constructor(name:string){
this.name=name;
}
}
let obj=new Person("园子");
obj.name="小D";
console.log(obj.name);//"小D"
class Person{
name:string;
private age:number;
constructor(name:string,age:number){
this.name=name;
this.age=age;
};
getAge(){
return this.age;
}
}
let obj=new Person("园子",20);
// obj.name="小D";
// obj.age=45;
console.log(obj.getAge());
class Person{
name:string;
protected age:number;
constructor(name:string,age:number){
this.name=name;
this.age=age;
};
protected getAge(){
return this.age;
}
}
class Docker extends Person{
getAge1(){
return super.getAge();
}
}
let obj=new Docker("园子",20);
// obj.name="小D";
// obj.age=45;
console.log(obj.getAge1());
class Person{
name:string;
private age:number;
constructor(name:string,age:number){
this.name=name;
this.age=age;
};
getAge(){
return this.age;
};
setAge(age:number){
if(age>=0){
this.age=age;
}
}
}
let obj =new Person("园子",26);
// obj.age=30;
obj.setAge(-25);
// obj.age=-30;
console.log(obj.getAge());
class Person{
name:string;
private age:number;
constructor(name:string,age:number){
this.name=name;
this.age=age;
};
get getAge(){
return this.age;
};
set setAge(age:number){
if(age>=0){
this.age=age;
}
}
}
let obj =new Person("园子",26);
obj.setAge=12;
console.log(obj.getAge);
详解TS中的泛型
泛型使⽤场景:
在定义函数或类时,如果遇到类型不明确就可以使⽤泛型,泛型就是⼀个不确定的类型
传进来是什么类型,传出去就是什么类型
问题:引出
function cache(value:number):number{
return value;
}
如何使⽤简单的泛型
function cache<泛型名>(value:泛型名):泛型名{
return 泛型名;
}
// 定义一个函数 把传入的参数并返回出去 接受一个字符串类型的参数prop 返回的类型也是字符串
function cache(prop:string):string{
return prop;
}
泛型的约束
// 我们可以指定泛型的类型,如果我们不指定TS解析器会根据我们传递的参数进⾏类型推测
// (建议我们在使⽤泛型的时候指定泛型的类型)
// 使⽤⽅法:
cache<指定泛型类型>('yuanzi');
创建多个泛型
//定义
function cache<泛型名1,泛型名2>(value1:泛型名1,value2:泛型名2):T{
return T;
}
//调⽤
cache<泛型类型1,泛型类型2>(实参1,实参2);
5、泛型在接⼝中的使⽤
//现在有个需求:实参可能是boolean string object 那么如何解决这个问题呢
//any 使用any的话,就会关闭ts的类型检测,不仅影响自己,还会在赋值时关闭其他变量的类型检测
// function cache(prop:any):any{
// return prop;
// }
// 使用泛型可以解决这个问题
// function cache<泛型名>(value:泛型名):泛型名{
// return 泛型名;
// }
// function cache<T,P>(prop:T,flag:P):T{
// return prop;
// }
// let a=cache<string,number>("true",1223);
// 定义了一个泛型接口 myInterface<T>,
// 其中 <T> 表示泛型类型参数,可以是任何类型。
// 接口中包含了一个属性 name,其类型为泛型类型参数 T。
// 这意味着在实现该接口时,可以指定 name 属性的具体类型。
interface myInterface<T>{
name:T;
}
// 这段代码定义了一个名为 Person 的泛型类实现了 myInterface<T>,
// 同时指定了两个泛型参数 T 和 P。
// 这个类实现了接口 myInterface<T>
// 其中 name 属性的类型是泛型 T,而 age 属性的类型是泛型 P。
// 泛型参数:<T, P> 指定了两个泛型参数 T 和 P,
// 它们可以在创建 Person 类的实例时设定为具体的类型。
class Person<T,P> implements myInterface<T>{
name:T;// Person 类有一个名为 name 的属性,其类型是泛型参数 T。
age:P; //Person 类有一个名为 age 的属性,其类型是泛型参数 P。
// name:T 和 age:P。它们对应 name 和 age 属性,将在构造函数中初始化
constructor(name:T,age:P){
this.name=name;
this.age=age;
}
}
// 创建实例:当创建 Person 类的实例时,需要提供具体的类型参数以及构造函数参数。
let obj=new Person<string,number>("园子",30);
console.log(obj);
更多推荐
所有评论(0)