目录
1.概念
TypeScript(简称:TS)是JavaScript的超集(JS有的TS都有)
TypeScript=Type+JavaScript(为JS添加了系统类型)
//TypeScript 代码: 有明确的类型: 如number (数值类型)
let age : number =18
//javascript 代码: 无明确的类型
let = 18
1.2优势
JS的类型系统存在“先天缺陷”,绝大部分的错误都是类型错误(Uncaught TypeError)。
- 优势一: 类型化思维方式,使得开发更加严谨,提前发现错误。
- 优势二:类型系统提高了代码可读性,并使维护和重构代码更加容易。
- 优势三: 补充了接口,杖举等开发大型应用时JS缺失的功能。
- Vue3源码使用TS重新写
- Angular默认支持TS:react与TS完美配合
2 使用
需要安装 node.js
node.js官网
2.1安装解析TS的工具包
- 在代码编辑器里打开终端
2.输入安装命令:npm i -g typescript敲回车来安装(需要联网)。
typescript:就是用来解析TS的工具包,提供了tsc命令,实现了TS->JS 的转化。
npm:用来安装前端开发中用到的包,是安装Node.js时自动安装的。
i(install):表示安装
-g(–global):全局标识,可以在任意目录中使用该工具
2.2 TS转换成JS过程
3第一个TS文件
3.1步骤
-
创建文件
①在桌面上创建文件夹:code
②在文件夹上点击鼠标右键,然后点击 Open With Code(用VSCode打开文件 )
③在VSCode中新建ts文件:hello.ts(注意:文件后缀名为. ts) -
写代码:在hello.ts 文件中输入以下代码,并保存
console.log('hello Ts')
问题1:TS代码能直接在Node.js里面运行吗? 不能
问题2:该如何处理? ①TS->JS代码 ② 执行JS
- 执行代码,分为两步:
①TS代码->JS代码:当前目录打开终端,输入命令 tsc hello.ts敲回车
②执行JS代码:输入命令node hello.js (注意:后缀为**.JS**)
解释:
- tsc hello.ts会生成一个hello.ts文件。
- node hello.js 表示执行这个js文件中的代码。
3.2简化执行TS的步骤
问题:每次修改代码后,都要重复执行两个命令才能执行TS代码,太繁琐。
执行TS代码的两个步骤:
1. tac hello. ta
2. node hello.js
简化方式:使用ts-node包,“直接" 在Node.js中执行TS代码。
- 安装命令: npm i-g ts-node.
- 使用方式: ts-node hello.ts.
解释: - ts-node 包内部愉偷的将TS-> JS,然后,执行JS代码。
- ts-node 包提供了命令ts-node,用来执行TS代码。
现在只需一一步:
ts-node hello.ts
4.输出语句
小结-TypeScript初体验
- TypeScript是JS的超集,为JS添加了类型系统。相比JS,开发体验更友好,提前发现错误,Bug更少,增加开发的幸福度。
- JavaScript的两个运行环境是: 1.浏览器 2.Node.js。
- TypeScript不能直接在浏览器或Node.js中执行。
- tsc 文件名.ts →文件名.js 。
- 如何简化执行TS代码:ts-node 文件名.ts。
- 注释方式1.单行注释 2.多行注释。
- console.log() 可以在终端(控制台)输出内容。
5.变量的使用
5.1 基本的使用
变量的使用分为两步:
第一步:声明变量并指定类型
let age:number;
解释:
- let是TS关键字,用来声明变量。
- age 是我们自己定义的变量名称。
- :number用来指定变量age为数值类型。
- 注意:分号是可选的。可省略
第二步:给变量赋值
age=10
解释
- 使用符号(=)来给变量age赋值
变量的使用小结
- 变量的两种使用方式: 1.先声明后赋值 2.声明的同时并赋值(推荐)
- 第一种:先声明后赋值
// 1.声明变量并指定 类型
let age:number
//2. 赋值
age=10
- 第二种.声明的同时并赋值(推荐)
let age:number=10
注意: 声明变量的时候要指定变量的类型
6.类型注解
- 示例代码
let age:number =18
代码中的 :number就是类型注解。
类型注解:是一种为变量添加类型约束的方式
程序员和TS有个约定。
// 变量age的类型为number(数值类型)
let age:number = 18
- 重要: 约定了什么类型,就只能给变量赋什么类的值。
// 错误示范
age= 'hello TS'
7.命名规范
7.1 命名规则
- 变量名称只能出现:数字、字母、下划线(_) 、美元符号($)、并且不能以 数字 开头
- 同时: 变量名称区分大小写。
// age 和 Age 是不同的变量
let age:number = 18;
let Age:number = 20;
7.2命名规范
- 变量名称要有意义,顾名思义。
//有意义
let age:number = 18
//无意义
let a:number = 18
- 使用驼峰命名法(首字母小写,后面每个单词首字母大写)。
let cityName;
let yourAge;
7.3小结
- 规则:变量名称只能出现数字、字母、下划线(_)、美元符号(
$
),并且不能以 数字 开头。
注意:变量名称区分大小写 - 规范:变量名称要有意义,顾名思义。
推荐:使用驼峰命名法(首字母小写,后面每个单词字母大写)
8.数据类型
8.1概括
- Typescript中的数据类型分为两大类:1.原始类型(基本数据类型) 2.对象类型(复杂数据类型)。
- 常用的基本数据类型有5个:number / string / boolean / undefined / null
8.2数字类型
- 数字类型:包含整数值和浮点型(小数)值
//数字类型:整数
let age:number= 18
//数字类型:小数
let acore:number = -99.9
- 当然,从另一个角度来看,也可以包含:正数和负数
//正数
let salary:number = +100000
//负数
let NegativeNumber:number = - 20000
8.3字符串类型
- 字符串:由零个或者多个字符串联而成的,用来表示文本信息。
console.log('hello ts')
console.log(' ') //空字符串
- 字符串可以使用单引号(’ ') 或双引号(" ") 建议(外双内单)
'hello ts' //推荐
"hello ts"
- 字符串类型的类型注解为:string ,声明变量时要添加类型注解。
let food:string = '糖葫芦'
8.4布尔类型
布尔类型,用来表示 真或假
只有两个值,分别是: true 和false。true表示真,false表示假。
布尔类型的类型注解为**:boolean**。
//真
let t:boolean = true
//假
let f:boolean = false
8.5undefined和null类型
共同特点: 只有一个值,值为类型本身。
undefined 类型的值为: undefined。
null 类型的值为: null。
//类型注解为:undefined
let u:undefinod = undefinod;
//类型注解为:null
let n:null = null;
区别
- undefinod:表示声明但未赋值的变量值(找不到值)。
let u:undefined
console.log(u) //输出为 undefined
- null:表示声明了变量并且已赋值,值为null(能找到值)
8.6小结
- Typescript 中常用的基本数据类型有5个
- 分别是: number(数字类型)/string(字符串类型)/boolean(布尔类型)/undefined/null
- 补充概念: 这些类型的值,也叫做字面量,也就是从字上就能看出来它是什么。
10 //数字字面量
'泡枸杞' //字符串字面量
true/false //布尔字面量
undefined
null
9.运算符
9.1概述
运算符 也称为操作符,用来实现 赋值(=)、算数运算符、比较等功能的符号。
9.2 算术运算符
算术运算符包含:加(+)、减(-)、乘(*)、除(/)。
算术运算符:进行算术运算时使用的符号,用于两个数值之间的计算。
//加
conaole.log(1 + 2) // 3
//减
console.1og(2 - 1) // 1
//乘
console.log(2★3) //1 6
//除
console.1og(4 / 2)//2
9.2.1加号的其他作用(字符串拼接)
- 注意: +号.不仅可以用于加法计算,还能实现字符串拼接。
//字符串拼接(拼申)
conaole.log('周杰' + '伦') //结果为: '周杰伦'
9.2.2加号引发的思考
9.3赋值运算符
9.4自增自减运算符
9.5比较运算符
9.6逻辑运算符
10.条件运算符
10.1 if 语句
10.2else语句
10.2.1if else语句练习
10.4 三元运算符
三元运算符的作用与if…else 语句类似。
作用:根据判断条件的真假,得到不同的结果。
语法:
结果= 判断条件 ? 值1 : 值2
解释:
- 如果判断结果为真,结果为 值1;
- 否则,如果判断条件为假,结果为 值2。
注意: 得到结果的类型 由值1 和值2 的类型决定(值1和值2的类型相同)。
11.循环语句
- 语法
for(初始化语句;判断语句;计数器更新){
循环体
}
解释
- 初始化语句:声明计数器变量,记录循环次数
- 判断条件:判断循环次数 是否达到目标次数。
- 计数器更新:计数器数量加1。
- 循环体:重复执行的代码,也就是要重复做的事情
for(let i:number=0;i<=3;i++){
console.log("第"+i+"次输出") //共输出 4 次
}
11.1break和continue
11.1.1 break
break 能够让循环提前结束(终止循环)
如下
for(let i:number=0;i<=5;i++){
if(i === 3){
break
}
console.log("第"+i+"次输出")
// 第3次输出后将会停止
}
11.1.2 continue
continue 能够让循环间断执行(跳过本次循环,继续下次循环)
for(let i:number=0;i<=5;i++){
if(i === 3){
continue
}
console.log("第"+i+"次输出")
// 第3次输出将会跳过
}
12.数组
数组,是用于存放多个数据的集合。
有数组:只需要使用一个数组( [ ] ),就可以存储任意多个数据。
12.1创建数组
创建数组有两种语法形式
12.1.1 语法一 (推荐)
let name:srting[] = []
** [ ] ** (中括号)表示数组,如果数组中没有内容,就是一个空数组
数组的类型注解由两部分组成**:类型+[ ]**,此处表示字符串类型的数组(只能出现字符串类型)。
let name:srting[] = ['元素0','元素1','元素2',...]
数组,多个元素之间使用逗号(,) 分隔。
数组中的每一项内容称为:元素。
12.1.2 语法二 (不推荐)
let name:string[] = new Array{}
功能与** [ ] ** 相同,但是更加繁琐:
let name:string[] = [ ]
数组中有数据的时候:
let name:srting[] = new Array{'元素0','元素1','元素2',...}
//相当于
let name:srting[] = ['元素0','元素1','元素2',...]
12.2 数组长度与索引
12.2.1 数组长度
数组长度: 表示数组元素的个数,通过数组的length 属性来获取。
let foods:srting[] = ['元素0','元素1','元素2','元素3']
// 获取数组长度
console.log(foods.length) //4
12.2.2 数字索引
数组中的每一个元素都有自己的序号。
我们把数组中的元素的序号,称为:索引(下标) , 数组中的元素 一一对应。
注意:数组索引是从0开始的。
let foods:srting[] = ['元素0','元素1','元素2','元素3']
// 数组的索引分变为 0 1 2 3
问题: 该数组的长度**(length)**和最大索引之间有什么关系?
最大索引为: length-1
12.2.3小结
总结
数组是有序的集合,用来存储多个数据。
问题1: 如何获取数组长度? 数组名.length
问题2:数组索引是从几开始的? 索引从0 开始
12.3取值和存值
12.3.1取值
从数组中,获取到某一个元素的值,就是从数组中取值 。 (比如,获取食物—煎饼)
let fooda:string[] = ['煎饼','馒头','米饭']
数组中的元素与索引是一一对应的,通过索引获取到某一个元素的值。
语法
数组名[索引号]
获取食物—煎饼
console.log(foode[0]) //煎饼
12.3.2存值
如果要修改数组中的某一个元素的值,就要使用数组存值。(比如,把馒头替换成包子)
let fooda:string[] = ['煎饼','馒头','米饭']
技巧:先获取到要修改的元素,然后,再存值。
语法
数组名[索引号] = 新值
把馒头替换成包子
fooda[1] = '包子'
console.log(fooda) // '煎饼','包子','米饭'
12.4 添加元素
存值的语法是**:数组名[索引号] = 新值**,根据**索引号是否存在,**有两种功能: 1.修改元素 2.添加元素。
let fooda:string[] = ['煎饼','包子','米饭']
- 如果索引号存在,就表示添加元素
fooda[3]='油泼面'
console.log(fooda) // '煎饼','包子','米饭','油泼面'
12.5 遍历数组
遍历数组,也就是把数组中的所有元索挨个获取一次(比如,计算数组中所有数字的和)。
let nums: number[] = [100, 200, 300]
//索引分别为: 0 1 2
推荐,使用for循环遍历数组:
for (let i: number = 0; i <= nums.1ength - 1; i++) {
console.1og (nums [1])
}
- 注意1:因为数组索引是从0开始的,所以计数器i的默认值为0。
- 注意2:应该根据数组长度来计算,公式为数组长度减一,也就是: nums. length - 1 (最大索引)。
- 优势:不管数组中元素的数量怎么变化,for循环的判断条件不需要改动。
简化判断条件(计数器i的值为整数,所以,i<=2与i<3作用相同) :
for (let i: number = 0; i < nums.length; i++) {
console. log (nums[i])
}
13.函数
所谓函数,就是声明一次但却可以调用任意多次的一段代码。
意义: 实现代码复用,提升开发效率
13.1 函数的使用
函数的使用分为两步: 1.声明函数 2.调运函数(类比变量)
- 第一步:声明函数
function 函数名(){
函数体
}
解释:
- 函数名:推荐以动词开头,因为函数表示做一件事情,实现一个功能。
- 函数体:表示要实现功能的代码,复用的代码
- 第二部:调用函数
函数名();
比如调用 sing函数
sing()
注意:只有调用函数后,函数中的代码才会执行。
小结
1.函数的基本使用分为哪两步?
- 1.声明函数
- 2.调用函数
2.声明函数的关键字是什么?
- funtion
3.不调用函数,函数中的代码会执行吗?
- 不会
//1. 声明函数
function sing(){
console.log('五环之歌')
}
//调用函数
sing();
13.2 函数参数
//调运函数时,告诉函数要唱的歌曲名称
sing('五环之歌');
sing('歌曲名称');
//声明函数时,接受传入的歌曲名称
function sing(songName:string){
console.log(songName)
}
函数(sing)中歌曲名称:
固定值→动态传入的值。
函数参数的作用:增加了函数的灵活性、通用性,针对相同的功能,能够适应更多的数据(值)
13.2.1 实参和形参
函数参数分为两部分: 1形参2实参。
1. 形参:声明函数时指定的参数,放在声明函数的小括号中(挖坑)。
function sing (songName: string) { }
- 语法:形参名称:类型注解,类似于变量声明,但是没有赋值。
- 作用:指定函数可接收的数据。
然后,就可以在函数体中,像使用变量一样使用形参了。
2.实参:调用函数时传入的参数,放在调用函数的小括号中(填坑)。
sing('五环之歌')
- 实参是一个具体的值(此如:字符串’、 18、[]等) ,用来赋值给形参。
形参和实参的总结:
- 声明函数时的参数,叫什么?作用?
形参,指定函数能够接收什么数据。
- 调用函数时的参数,叫什么?作用?
实参,是一个具体的值,用来赋值给形参。
function sing (songName: string) { }
sing('五环之歌')
通过形参和实参的配合,函数可以接收动态数据,从而让函数变得更加灵活、强大。
13.2.2 其他说明
- 根据具体的功能,函数参数可以有多个,参数之间使用逗号(,) 来分隔。
function fn(name: string, age: number) { }
fn('刘老师',18)
- 实参和形参按照顺序,-对应。
function fn (name: string,age: number) { }
fn('刘老师',18) // name -> ' 刘老师',age -> 18
- 实参必须符合形参的类型要求,否则会报错!
function sing (songName: string) {}
sing(18) //1 报错!形参要求是 string类型,但是,实参是number类型。
技巧:调用函数时,鼠标放在函数名称上,会显示该函数的参数以及类型。
小结
- 函数形参是string类型,调用该函数时传入18对吗?
不对,因为实参不符合形参的类型要求
- 函数有多个参数时,多个参数之间用什么符号分隔?
逗号
- 以下代码会报错吗?
报错!因为函数sing要求有一个参数,但是没有传
function sing (songName: string) { }sing() /1 报错!
13.3 函数返回值
- 函数返回值的作用:将函数内部计算的结果返回,以便于使用该结果继续参与其他的计算。
13.3.1 基本使用
步骤: 1指定返回值类型2指定返回值
1.指定返回值类型
function fn(): 类型注解{
}
- 在声明函数的小括号后面,通过:类型注解指定。
function fn() : number {
}
2.指定返回值
function fn(): 类型注解{
return返回值
}
- 在函数体中,使用return 关键字来返回函数执行的结果。
function fn() : number {
return 18
}
- 注意:返回值必须符合返回值类型的类型要求,否则会报错!
小结
1. 使用变量接收函数返回值
let result:类型注解= fn()
使用变量接收函数返回值的时候,相当于:直接将返回值赋值给变量。
let result: number = 18
注意:变量(result) 的类型与函数(fn) 的返回值类型要-致。
然后,就可以使用这个变量(返回值),继续进行其他计算 了。
2.直接使用函数调用的结果 (返回值), 进行其他计算
console.log( fn() *10 )
13.3.2 return 的说明
1. 将函数内部的计算结果返回。
2. 终止函数代码执行,即: return后面的代码不会执行。
function fn() : number {
return 18
console.log('我不会执行,放在这,没有意义')
3. return 只能在函数中使用,否则会报错。
4. return可以单独使用(后面可以不跟内容),用来刻意终止函数的执行。
function play(age: number) : void {
if(age<18){
return
}
console. log('网吧上网好爽啊,王者、吃鸡两不误)
}
play(16) //情况1:进入if后return, 后续代码不执行
play(20) //情况2:不进if,直接打印内容:网吧 上网好爽啊,王者、吃鸡两不误
注意:如果函数没有返回值,默认返回值类型是: void (空),可省略不写。
function play(age: number) { /* ... */ }
return的小结
- 能否在函数外面使用 return?
不能
- return 后面的代码会执行吗?
不会执行
- return 后面不跟内容,单独使用,表示什么?
刻意终止函数代码执行
- 函数没有返回值, 默认返回值类型是什么?
void
13.4 总结
-
函数,即:声明一次但却可以调用任意多次的一段代码。
-
通过将要实现的功能,使用函数封装起来,实现代码复用,提升开发效率。
函数的三种主要内容:
1.参数 – 可选
2.函数体
3.返回值。-- 可选
14.函数进阶
14.1 调试的基本操作
结论1:函数里面,还可以继续调用其他函数。
结论2:函数,按照顺序-行行的执行代码,当遇到调用其他函数时,先完成该函数调用,再继续执行代码。
14.2 变量的作用域
一个变量的作用域指的是:代码中定义变量的区域,它决定了变量的使用范围。
在TS (或Js)中,函数可以形成作用域,叫做:函数作用域。
根据范围的不同,变量可以分为两种:
1.局部变量 2.全局变量。
-
局部变量:表示在函数内部声明的变量,该变量只能在函数内部使用(局部地区有雨)。
-
全局变量:表示在函数外部声明的变量,该变量在当前ts文件的任何地方都可以使用。
//变量num是全局变量
let num: number = 1
function fn() {
console.1og (num) // 问题:此处能访问到变量num吗?
}
fn()
console. log (num) // 问题:此处能访问到变量num吗?
15.对象
TypeScript中的对象,是对生活中具体事物的抽象,使得我们可以通过代码来描述具体的事物。TS中的对象,也是由特征和行为组成的,它们有各自专业的名称:属性(特征)和方法(行为)。
- 理解TS中的对象: -组相关属性和方法的集合,并且是无序的。
//演示对象:
{
name: '周杰伦',
gender: '男',
height: 175,
sing: funtion () {
console. log('故事的小黄花从出生那年就飘着')
}
}
- 疑问:为什么要有对象?
需求:使用TS代码描述周杰伦。
- 方案二:使用数组,- -次可以存储多个数据:
['周杰伦',男',175, function sing() { ... }]
- 缺点:不知道数组中的每个元素表示什么。
正确姿势:使用对象,对象在描述事物(- 组相关数据)时,结构更加清晰、明了。
{ name: ' 周杰伦',gender:'男',height: 175, sing: function () { .... }}
15.1 创建对象
先学习对象的基本使用,再学习对象的类型注解(对象的类型注解类似于对象自身的语法)
对象的语法:
let person = {}
此处的 {} (花括号、大括号) 表示对象,而对象中没有属性或方法时,称为 :空对象。
对象中的属性或者方法,采用键值对的形式,键、值之间使用冒号 ( : ) 来配对。
let person = { let person = {
键1:值1, name:‘老师’,
键2:值2 ---> age:18
} }
键(key) -> 名称,值(value) -> 具体的数据。
多个键值对之间,通过逗号 (,)来分隔 (类比数组)
现在,对象 person 具有两个属性:
let person = {name:'老师',age:18}
属性和方法的区别: 值是不是函数,如果是,称为方法;否则就是普通属性。
let person = {
sayHi:function(){
console.log('我是方法')
}
}
注意:函数用作方法时可以省略 function 后面的函数名称,也叫做匿名函数。
函数没有名称,如何调用? 此处的sayHi相当于函数名称,将来通过对象的sayHi就可以调用了。
如果一个函数是单独出现的,没有雨对象关联,我们称为函数;否则,称为方法。
15.2 接口
15.2.1 对象属性的类型注解
TS中的对象是结构化的,结构简单来说就是对象有什么属性或方法。
在使用对象前,就可以根据需求,提前设计好对象的结构。
比如,创建一个对象, 包含姓名、年龄两个属性。
- 思考过程:
1.对象的结构包含姓名、年龄两个属性
2.姓名→字符串类型,年龄→数值类型
3.创建对象。
let person: {
name: string;
age: number;
}
↓
person = {
name: ' 刘老师',
age: 18
}
这就是对象的结构化类型(左侧) ,即:对该对象值(右侧) 的结构进行类型约束。
或者说:建立一种契约,约束对象的结构。
-
注意:键值对中的值是类型! (因为这是对象的类型注解) 。
-
注意:多个键值对之间使用分号( ; ) 分隔,并且分号可省略。
//此处的{}表示对象的类型注解
let person:{
name: string;
age: number
}
//此处的{ }表示ts中的对象
person = {
name :
刘老师',
age: 18
}
15.2.1 对象方法的类型注解
问题:如何给对象中的方法,添加类型注解?
- 技巧:鼠标放在变量名称上, VSCode就会给出该变量的类型注解。
let person: {
sayHi: () => void
sing: (name: string) => void
sum: ( numl: number, num2: number) => number
}
- 箭头(=>) 左边小括号中的内容:表示方法的参数类型。
- 箭头(=>) 右边的内容:表示方法的返回值类型。
- 方法类型注解的关键点: 1参数2返回值。
15.2.2 接口的使用
直接在对象名称后面写类型注解的坏处:
1.代码结构不简洁
2.无法复用类型注解。
接口:为对象的类型注解命名,并为你的代码建立契约来约束对象的结构。
语法:
interface IUser {
name: string
age: number
}
↓
let p1: IUser = {
name: 'jack',
age: 18
}
15.3 取值和存值
15.3.1 取值
取值,即:拿到对象中的属性或方法并使用。
获取对象中的属性,称为:访问属性。
获取对象中的方法并调用,称为:调用方法。
- 访问属性
let jay = { name: '周杰伦', height: 175 }
需求:获取到对象(jay) 的name属性。
console.log (jay . name)
说明:通过**点语法(.)**就可以访问对象中的属性。
技巧:在输入点语法时,利用vsCode给出来的提示,利用上下键快速选择要访问的属性名称。
●调用方法
letjay={
sing: function () {
console. log('故事的小黄花从出生那年就飘着')
}
}
需求:调用对象(jay) 的sing方法,让他唱歌。
jay.sing()
说明:通过点语法(.) 就先拿到方法名称,然后,通过小括号调用方法。
https://bloq.youkuaiyun.comac 46204.
补充说明:
console.log(参数1,参数2,...)
实际上,console是一个对象,而1og是该对象提供的一个方法。
并且,log方法可以有多个参数。
console.log('我叫',jay. name)
小结:
- 通过什么符号,来访问对象中的属性或方法?
点语法(.) - 注意:方法需要调用,所以,通过点语法拿到方法名称后,不要忘记使用小括号调用!
- 技巧:通过点语法,访问对象属性时,利用vscode出来的提示,快速选择要访问的属性或方法。
- 该技巧很实用,特别是访问别人创建的对象时(比如: console对象)。
15.3.2 存值
存值,即修改(设置)对象中属性的值。
let jay = { name: '周杰伦',height: 175 }
需求:将对象(jay) 的name属性的值修改为周董。
jay.name = '周董'
解释:先通过点语法获取到name属性,然后,将新值’周董"赋值给该属性。
console.log (jay.name) // 周董
注意:设置的新值,也必须符合该属性的类型要求!
注意:几乎不会修改对象中的方法。
15.4 内置对象
建议多看文档
TypeScript文档参考
JavaScript文档参考 MDN
15.4.1 数组对象-forEach 循环
forEach的使用说明:
songs . forEach (function (item, index) {
console.log('索引为',index, ' 元素为',item)
})
注意: forEach 方法的参数是一个函数, 这种函数也称为回调函数。
forEach方法的执行过程:遍历整个数组,为数组的每一项元素,调用一次回调函数。
回调函数的两个参数:
- item表示数组中的每个元素,相当于songs [i]。
- index表示索引,相当于i.
- 疑问:不需要为回调函数的参数或返回值指定类型注解吗?
注意: 此处的回调函数,是作为forEach方法的实参传入,不应该指定类型注解!
forEach方法,可以根据当前数组的类型,自动推导出回调函数中参数的类型。
注意:回调函数中的参数可以用任意名称,并且,如果没有用到,可以省略。
songs. forEach (function (a, b) {}) // OK! a>数组元素b →索引
songs. forEach (function (item) {}) // OK!索引没用到,直接省略
15.4.2 数组对象- some
some方法:遍历数组,查找是否有一个满足条件的元素(如果有,就可以停止循环)。
循环特点:根据回调函数的返回值,决定是否停止循环。如果返回true,就停止;返回false,就继续循环。
let has: boolean - nums。some (function (num) {
if(num>10){
return true
}
return false
}
some方法的返回值:布尔值。如果找到满足条件的元索,结果为true;否则,为false.
104
补充:TS的类型推论
在TS中,某些没有明确指出类型的地方,类型推论会帮助提供类型。
换句话说:由于类型推论的存在,这些地方,类型注解可以省略不写!
发生类型推论的2种常见场景: 1声明变量并初始化时2决定函数返回值时。
let age+ number = 18
//=>
let age = 18
------------
function sum (huml: number, num2: number)+ number { return numl + num2 }
// =>
function sum (num1: number, num2: number) { return num1 + num2 }
注意:这两种情况下,类型注解可以省略不写!
推荐:能省略类型注解的地方,就省略(偷懒、充分利用Ts类型推论的能力,提升开发效率)。.
自动刷新浏览器–Vscod插件
在浏览器中运行TS
注意:浏览器中只能运行Js,**无法直接运行Ts,**因此,需要将Ts转化为Js然后再运行。
浏览器中运行TS的步骤:
- 使用命令tse index. ts将ts文件转化为js文件。
- 在页面中,使用script标签引入生成的js文件(注意是js文件)。
<script src="./index. js"></script>
- 问题:每次修改ts文件后,都要重新运行tsc命令将ts转化为js.
解决方式:使用tsc命令的监视模式。
tsc --watch index. ts
解释: --watch 表示启用监视模式,只要重新保存了ts文件,就会自动调用tsc将ts转化为js。
16.类型断言
- 问题:调用querscrySelector()通过id选择器获取DOM元素时,拿到的元素类型都是Element。
因为无法根据id来确定元素的类型,所以,该方法就返回了一个宽泛的类型:元素(Element)类型。
不管h1还是img元素。
导致新问题:无法访问img元素的src属性了。
因为:Element 类型只包含所有元素共有的属性和方法(比如:id属性)
解决方式:使用类型断言,来手动指定更加具体的类型(比如,此处应该比Element类型更加具体)。
语法:
值 as 更具体的类型
比如:
let img = document.querySelector('#images') as HTMLIamgeElement
解释:我们确定id = “images” 的元素是图片元素,所以,我们将类型指定为HTMLIamgeElement。
技巧:通过console.dir()打印DOM元素,在属性的最后面,即可看到该元素的类型
小结
类型断言:手动指定**更加具体(精确)**的类型。
使用场景:当你比TS更了解某个值的类型,并且需要指定更具体的类型时。
// document . querySelector()方法的返回值类型为: Element
//如果是h1标签:
let title = document . querySelector('#title') as HTMLHeadingElement
//如果是img标签:
let image = document . querySelector('#image') as HTMLImageEl ement
- 技巧:通过console.dir ()打印DOM对象,来查看该元素的类型。
17.取元素
17.1获取单个元素
- 获取一个DOM元素:
document . querySelector (selector)
document对象:文档对象(整个页面),是操作页面内容的入口对象。
sclector参数:是一个css 选择器(标签、类、id选择器等) .
作用:查询(获取)与选择器参数匹配的DOM元索,但是,只能获取到第一个!
推荐:使用id选择器(唯一)。
let title = document .querySelector('#title')
- 解释:获取页面中id为title的DOM元素。
17.2获取多个元素
document . querySelectorAll (selector)
作用:获取所有与选择器参数匹配的DOM元素,返回值是一个列表。
推荐:使用class选择器
示例:
let list = document . querySelectorAll(' .a')
- 解释:获取页面中所有class属性包含a的元素。
17.3操作文本内容
读取:
dom. innerText
设置:
dom. innerText = '等你 下课'
- 注意:需要通过类型断言来指定DOM元索的具体类型,可以使用innerText属性。
- 注意:设置内容时,会覆盖原来的内容。如何实现追加内容(比如,青花瓷>青花瓷-周杰伦) ?
dom. innerText = dom. innerText + ' -周杰伦'
//简化
dome. innerText +='.周木伦'
17.4操作样式
1. style属性(行内样式)
读取:
dom.style.样式名称
设置:
dom.style.样式名称=样式值
- 说明:所有的样式名称都与CSS相通,但命名规则为驼峰命名法。
dom. style. fontSize = '30px'
dom.style.display = 'none '
2. classList 属性(类样式)
- 包含三个常用方法:添加、移除、判断是否存在。
添加:
dom.classList.add(类名1,类名2,...)
- 参数表示:要添加的类名,可以同时添加多个。
比如:
<P class="a"></p>
dom. classList.add('b', 'c')
//添加class样式==> class="a b c"
移除:
dom. classList. remove(类名1,类名2, ...
- 参数表示:要移除的类名,可以同时移除多个。
比如:
<p class="a b c"></p>
dom.classList. remove('a', 'c')
//移除class样式==> class="b"
17.5移除:
dom. classList. remove(类名1,类名2,...
参数表示:要移除的类名,可以同时移除多个。
比如:
<p class="a b c"></p>
dom. classList. remove('a', 'c')
//移除class样式==> class="b"
17.6判断类名是否存在:
let has = dom. classList. contains(类名)
参数表示:要判断存在的类名。
比如:
<p class="b"></p>
dom. classList. contains('a')// false
dom. classList. contairts('b')// true
17.7总结:
类样式(classList)的操作有三种:
//添加
dom. classList.add('a', 'b')
// 移除
dom. classList. remove('b', 'c')
//判断是否存在
let has = dom. classList. contains('a')
18.操作事件
1. addEventListener添加事件
作用:给DOM元素添加事件。
dom. addEventListener (事件名称,事件处理程序)
事件名称:字符串,比如: ‘click’ (鼠标点击事件)、‘mouseenter’ (鼠标进入事件)。
事件处理程序:回调函数,指定要实现的功能,该函数会在触发事件时调用。
- 示例:鼠标点击按钮,打印内容。
btn. addEventListener('click', function () {
console. log('鼠标点击事件触发了')
事件对象
- 事件对象(event) ,是事件处理程序(回调函数)的参数。
表示:与当前事件相关的信息,比如:事件类型(type) 、触发事件的DOM元素(target) 等。
btn. addEventListener('click', function (event) {
console.log (event. type)// click
console. log (event. target)// btn元素
})
2. removeEventLi stener移除事件
正确方式:
function handleClick() { }
btn. addEventListener('click', handleClick)
btn. removeEventListener('click', handleClick)
- 说明:添加和移除事件时,事件处理程序是同一个,都是函数handleClick.
错误演示:
btn. addEventListener('click', function () {})
btn . removeEventListener ('click', function () {})
注意:以上两个函数虽然长的一样,却是不同的函数(双胞胎,不是同一个人)
once属性
- 如果事件只需要触发一 次,可以在添加事件时处理。
处理方式:传入第三个参数,将once属性设置为true。
btn. addEventListener('click', function () {}, { once: true })
once: 如果值为true,会在触发事件后,自动将事件移除,达到只触发- 次的目的。
移除事件总结:
当DOM 元素的事件不再使用时,就可以通过removeEventListener 方法移除事件。
注意:添加和移除的事件处理程序必须是同一个,否则无法移除!
function handleClick() {}
btn. addEventListener('click', handleClick)
btn. removeEventListener('click',handleClick)
- 如果事件只需要触发一次,可以在添加事件时,通过once属性来实现。
btn. addEventListener('click', function () {}, { once: true })
19.函数声明形式的事件程序说明
1. 可以先使用函数, 再声明函数。
btn. addEventListener ('click',handleClick)
function handleClick() {}
- 原因:函数声明在当前ts文件中的任意位置都有定义。
// 1先调用函数
fn()
//2再声明函数
function fn() {}
2.使用事件对象参数时, 应该指定类型注解,否则,访问事件对象的属性时没有任何提示。
btn. addEventListener('click', handleClick)
function handleClick (event: MouseEvent){
console.log (event. target)
}
- 技巧:使用原始方式(匿名回调函数)查看参数类型。
20.枚举
使用枚举: .
枚举是一种类型,因此,可以其作为变量的类型注解。
enum Gender { Female, Male }
let use rGender: Gender
- 访问枚举(Gender)中的成员,作为变量(use rGender)的值:
userGender= Gender. Female
userGender = Gender .Male
- 注意:枚举成员是只读的,也就是说枚举中的成员可以访问,但是不能赋值!
Gender.Female = '男'//错误
20.1枚举的基本使用总结:
- 枚举是组织有关联数据的一-种方式。
- 使用场景:当变量的值,只能是几个固定值中的一个,应该使用枚举来实现。
enum Gender { Female, Male }
let userGender: Gender = Gender.Male
注意点:枚举中的成员建只读的,因此,只能访问不能赋值!
20.2数字枚举
问题:将枚举成员赋值给变量,变量的值是什么呢?
enum Gender { Female, Male }
let userGender: Gender = Gender . Female
console. log (userGender) // ? 0
枚举成员是有值的,默认为:从0开始自增的数值。
我们把,枚举成员的值为数字的枚举,称为:数字枚举。
当然,也可以给枚举中的成员初始化值。
enum Gender { Female = 1, Male }// Female => 1 Male => 2
enum Gender { Female = 1,Male = 100 } // Female => 1 Male => 100
20.3字符串枚举
字符串枚举:枚举成员的值是字符串。
enum Gender { Female = '女',Male = '男}
- 注意:字符串枚举没有自增长行为,因此,每个成员必须有初始值。
console. log (Gender. Female) //女
console.log (Gender.Male)// 男
20.4小结
1.数字枚举:枚举成员的值为数字,默认情况下就是数字枚举
enum Gender { Female, Male }
enum Gender { Female = 100, Male } // 初始化成
特点:成员的值是从0开始自增的数值。
2.字符串枚举:枚举成员的值为字符串。
enum Gender { Female = '女',Male = '男' }
特点:没有自增行为,需要为每一个成员赋值!
枚举是一组有名字的常量 (只读)的集合。
21.井字游戏