JavaScript三大核心:
ECMAScript:JS基础语法
Bom:browser object model 浏览器对象模型
在bom中给我们提供了一些可以操作浏览器的属性和方法。
Dom:document object model 文档对象模型
在dom中给我们提供了很多可以操纵文档(页面上的标签)的属性和方法,只要css可以控制的dom都可以操作
行内式(内嵌式):写在元素内部,一般不常用。
a:"javascript: alert('11');">超链接
非a:
内部式:可以存在多个,且可以和内嵌式同时存在。
外链式:外链式的script标签中是不可以书写js代码的,写了也会被忽略掉,最常用。
单行注释:ctrl + /
多行注释:alt + shift + a
用来存储和表示数据的容器。
用来存储和表示数据的容器,且运行中,变量的值可能会发生变化,必须要定义才能输出。
用来存储和表示数据的容器,且运行中,常量的值不会发生变化,不需要定义即可输出。
语法一:(声明并赋值)
var 变量名 = 值(数字,字符串(''/""引起来),true,false)
语法二:(先声明再赋值)
var 变量名;
变量名 = 值
语法三:(先声明多个再赋值)
var 变量名1,变量名2,变量名3;
变量名1 = 值1;
变量名2 = 值2;
变量名3 = 值3
报错:Uncaught ReferenceError: a is not defined(变量未定义)
var a = 20; 创建一个a的变量,并赋值为20
a = 10; 给a重新赋值
此时a便是10,20则会被覆盖
alert(输出内容)//弹出框弹出
console.log(输出内容) //控制台打印
document.write(输出内容) //页面输出,可以识别标签
变量的命名规则(必须要遵守,不遵守会报错):
1.变量名组成是由 数字、字母、下划线(_),美元符号($)组成
2.不能以数字开头
3.不能是关键字或保留字(被js赋予特定含义的单词):
关键字:break、do、instanceof、typeof、case、else、new、var、catch、finally、return、void、continue、for、switch、while、debugger、function、this、with、default、if、throw、delete、in、try
保留字:abstract、enum、int、short、boolean、export、interface、static、byte、extends、long、super、char、final、Native、synchronized、class、float、package、throws、const、goto、private、transient、 debugger、implements、protected、volatile、double、import、public
4.严格区分大小写,var和Var不是一个意思
5.汉子也可以作为变量名出现,但是极度不推荐
变量的命名规范(建议遵守):
1.见名知意
2.小驼峰命名法(第一个单词小写,第二个单词开始,首字母大写) applePrice
1.数字类型 number
整数、小数、科学计数法、NaN(尝试将其他类型转换为数字类型,转换失败的产物)
八进制:0开头
十六进制:0x开头 0-9和a-f
二进制:0b开头
2.字符串类型 string
英文""双引号或''单引号包裹的都是字符串
\ 转义字符
\n 代表换行 \t 代表tab键 \\ 代表的是 \ \' 代表的是'
拼接:任何类型与字符串拼接(+),结果都为字符串
3.布尔类型 boolean
true:真 参与数学运算时为1
false:假 参与数学运算时为0
4.未定义类型:undefined
定义了一个变量,但没有给变量赋值,则该变量值为undefined
5.空类型:null
当一个变量将来要被赋值为复杂数据类型时,可以使用null来定义
1.数组:数组里面可以存储很多条数据,数组的单词是array,数组的标志是[]。(详见P20)
2.对象(P18)
3.时间对象(P24)
4.函数
内存可以分为栈内存、堆内存
简单数据类型:都是直接存储在栈中
复杂数据类型:变量在栈中,数据在堆中,会把堆的内存地址赋值给栈中的变量。//所以变量中存的不是数据而是地址
简单数据类型一个改变不会影响到其他
复杂数据类型如果公用一个地址,一个改变,会影响到其他
typeof 检测数据类型:
语法一:typeof 要检测的内容
语法二:typeof(要检测的内容)
结果:以字符串的形式显示检测的类型
Array.isArray() 检测是否是数组类型//是则true,否则false
A instanceof B 检测a是否是b类型
1.为什么要类型转换?
输入框输入的值都是字符串,如果需要运算,则需要把输入的字符串转换为数字,再进行运算。
2.转数字类型的三种语法(js内置提供的三种方法):
2.1 语法:Number(变量)
结果:以数字类型呈现
转换的规则:1.纯数字的字符串转为数字
2.true转为1,false转为0
3.其他类型转为NaN
2.2 语法:parseInt(变量)
结果:以数字类型呈现
转换的规则:1.纯数字的字符串转为数字
2.以数字开头的字符串,可以转为数字
3.true和false转为NaN
4.其他类型转为NaN
5.转整数,有小数直接省掉
2.3 语法:parseFloat(变量)
结果:以数字类型呈现
转换的规则:1.纯数字的字符串转为数字
2.以数字开头的字符串,可以转为数字
3.true和false转为NaN
4.其他类型转为NaN
5.转小数,有小数点就可以转换
1.1 语法:String(变量名)
可以任意类型转换为字符串
1.2 语法:变量名.toString()
除了undefined、null,可以将任意类型转换为字符串
1.1 语法:Boolean(变量名)
只有''、0、NaN、null、undefined、false被转换为false,其余都是true
1.算术运算符:+ - * / %(取余)
+ 拼接:字符串+数字 / 字符串+字符串
2.关系运算符:> < >= <= == === !=
比较的结果为布尔类型
== 与 === ==只比较值(会隐式转换),而===不但比较值,还比较类型
3.赋值运算符:= += -= *= /= %=
赋值运算符可以让变量的值,发生改变
4.逻辑运算符:|| && !
表达式:能够计算出一个结果的式子:例1+2、2>3
条件表达式:能够计算出真或假的表达式 4>2
|| 一真及真,都为假为假,短路,前面为假则不看后面
&& 一假及假,都为真为真,短路,前面为真则不看后面
! 真为假,假为真
5.自加自减运算符:++ --
含义:a++ 、++a 自身加1
a-- 、--a 自身减1
相同点:都加一或减一
不同点:在参与输出,运算,赋值等操作时,a++先执行这些操作,再加1
++a先加1,再执行这些操作
+:数字+字符串 会将数字转换为字符串
- * / % > < == 数字 - 字符串 隐式会将字符串转换为数字
isNaN(内容):等价于isNaN(Number(内容))//会隐式转换
检测内容是否为非数字,如何是非数字,结果则为true
如果是数字,结果则为false
if 语法:
if单分支:
语法:if(条件表达式){语句体;}
执行流程:条件表达式成立,就执行语句体,不成立就不执行
if双分支:
语法:if(条件表达式){语句体1;}else{语句体2;}
执行流程:条件表达式成立,就执行语句体1,不成立就则执行语句体2
if多分支:
语法:if(条件表达式1){语句体1;}
else if(条件表达式2){语 句体2;}
else{语句体3}
执行流程:条件表达式1成立,就执行语句体1,条件表达式2成立,就执行语句体2,都不成立就则执行语句体3
分支语句的嵌套:
语法:if(条件表达式){
if(条件表达式){
语句体;
}
}
//if (表达式)----等价于if(boolean(表达式)){}
//if (表达式) alert("")只有一行时,可以省略{},但不推荐
switch 语法:
switch (key) {
case value:
语句体;
break;
case value:
语句体;
break;
default:
语句体;
break;
}
执行流程,拿着switch里的key和case后的value进行精准匹配(全等匹配),成功就执行,都不匹配则执行default。
注意事项:依次向下执行,不写break会穿透,遇到break中止,key一般为变量,value为常量。
while 语法:
初始化变量;
while(表达式){
循环体;
变量的更新
}
先判断表达式,为true再执行,false则直接结束
do while 语法:
初始化变量;
do{
循环体;
变量的更新
}while(表达式)
先执行一次循环体,再判断表达式,为true再执行,false则直接结束
for 语法:
for(表达式1;表达式2;表达式3){
循环体;
}
循环嵌套:
1.外层循环控制行数
2.内层循环控制每行执行的个数
3.外层循环每走1次,内层循环执行一轮
break :用于 switch 、循环语句
用在循环里:终止本层循环。
continue :
用在循环里:跳过本次循环,继续执行下一次循环
函数就是把完成特定功能的一段代码抽取出来,使之成为程序中的一个独立实体,起个名字(函数名)。
可以在同一个程序或其他程序中多次重复使用(通过函数名调用)
定义函数的语法:
function 函数名([形参1,形参2...]){,
函数体
}
var 函数名 = function() {
函数体
}
调用函数的语法:
函数名(实参1,实参2);
调用时:1、实参-传递给形参2、代码从上到下
注意点:
1. 函数不调用,则不执行
2. 函数名遵循变量的命名规则和规范
3. 定义函数的参数叫形参。
return 返回值:
1.可以带出一个函数的运算结果
2.终止函数的作用
3.任何函数都是有return,如果不写,系统会自带一个return undefined
arguments :任何函数都有的一个方法,接收所有的实参
1、浏览器在解析代码时,会将 var 和 function ,提升到作用域最顶端。
2、然后从上往下依次执行
3、函数提升和变量提升同时存在时,函数提升优先于变量提升
1、概念:一段代码生效的范围,分为全局作用域和局部作用域。
全局变量和局部变量的区别:
全局变量:
定义位置:script内部,函数外部。
访问的位置:都可以访问
生命周期:打开页面产生,页面关闭销毁
局部变量:
定义位置:函数的内部
访问的位置:只能在定义的函数内部访问
生命周期:函数调用时产生,调用完毕立马销毁
2、访问规则:
先在自己作用域查找,有就拿来用,没有则向上一级查找,依次类推,如果全局作用域也没有,则报错。
3、赋值规则:
先在自己作用域内部查找,有就直接赋值
没有就去上一级作用域内部查找,有就直接赋值,依次类推
如果一直找到全局作用域都没有,那么就把这个变量定义为全局变量,再给他赋值
4、作用域链:
各个作用域互相嵌套,链接成的域,叫做作用域链
1、对象:编程界万事万物皆对象。
抽取出的两个概念:特征(属性)、行为(方法)
/*对象的键值对
键名的命名规则:
1.符合变量命名规则的都是可以作为键名
2.可以是纯数字
3.可以是一些特殊的符号,但是要求用双引号包裹
键具有唯一性:一个对象中不会出现重复的键
*/
2、声明方式:
var 对象名 = {
属性名 : 属性值
方法名 : function(){
方法体
}
};
3、访问对象的属性或方法:
对象名.属性名
对象名.方法名()
4、对象的增删改查:
写法1: .语法 //.语法的键无法识别变量,会把点后面的当做字符串处理
增:对象名.属性名 = 属性值
删:delete 对象名.属性名
改:对象名.属性名 = 属性值
查:打印
写法2: []语法 //[]语法会把键当成变量,如果[属性名]属性名添加了引号会识别成字符串
增:对象名[属性名] = 属性值
删:delete 对象名[属性名]
改:对象名[属性名] = 属性值
查:打印
5、对象的遍历
//第一种:for...in...
for(var key in obj){
key//所有键
obj[key]//所有值
}
//第二种:
Object.keys(obj):以数组形式返回所有键
Object.values(obj):以数组形式返回所有值
1、获取标签:var name = document.getElementById("id名")
2、获取输入框值:name.value
3、给输入框赋值:name.value = 值
4、点击事件: 标签.onclick = function(){}
练习:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BdX3pqOd-1676513233479)(E:\web\course\JavaScript\笔记\assets\1672382978364.png)]
概念:一组数据的有序的集合
方式一:字面量方式
语法: var 变量名 = [数据1,数据2,数据3]
方式二:内置构造函数方式:
语法: var 变量名 = new Array(数据1,数据2,数据3)
方式二创建数组时,如果只输入一个数字,则创建的是一个长度为该数字的数组,如var x = new Array(10),则表示创建了一个长度为10的数组,此时没有给数组赋值,会用empty占位
一个数组中可以存储不同类型的数据,但建议只存储同一种类型数据
//Array.isArray(arr); 检测arr是否是数组,是数组返回true,不是返回false
// arr instanceof Array; 检测arr是否为数组,是数组返回true,不是返回false
伪数组转数组:Array.from()
1.获取:
语法: 数组名.length
2.设置
语法: 数组名.length = 数字
将数组长度设置的比初始长度小,会从后往前删除到符合长度为止。
将数组长度设置的比初始长度大,会用empty占位到符合长度为止。
将数组长度设置的和初始长度一样,数组无变化。
1.数组的索引
数组中数据的编号,叫做索引,或者叫下标
数组中索引是从左到右,从0开始依次加1
数组的规律:数组最小索引为0,最大索引为length - 1
2.通过索引获取数组中的数据
语法: 数组名[索引]
如果索引存在,则可以得到对应数据
如果不存在,则结果为undefined
3.通过索引设置数据
语法:数组名[索引] = 值
如果索引存在,则修改对应的数据
如果不存在,索引大于数组长度,则使用empty占位将,数组长度追加到该索引值,并将该索引值修改为对应数据
1. 遍历:从头到尾挨个访问一遍
遍历数组:从头到尾挨个访问一遍该数组中的数据
2. 使用for循环遍历数组:
//方法一:for 循环变量是索引
for (var i = 0; i < 数组名.length; i++) {
数组名[i]
}
//方法而:for...in 循环变量是索引
for (var i in arr) {
arr[i]
}
//方法三:for...of 循环变量是元素
for (var value of arr) {
value
}
1. push()://向数组的末尾追加一条或多条数据
语法:数组名.push(数据...)
返回值:追加数据后数组的长度
//底层原理:
arr[arr.length] = 加的数据
2. pop()://从数组的末尾删除一条数据
语法:数组名.push()
返回值:被删除的数据
3. unshift()://从数组开头添加一条或多条数据
语法:数组名.unshift(数据)
返回值:添加数据后数组的长度
4. shift()://从数组开头删除一条数据
语法:数组名.shift()
返回值:被删除的数据
5. reverse()://反转数组
语法:数组名.reverse()
返回值:反转后的数组
6. sort()://对数组中数据进行排序
语法1:数组名.sort()
默认排序规则为:一位一位进行比较
//形参a和b可以随意起名字
语法2:数组名.sort(function(a,b){
return a-b;//从小到大排序
return b-a;//从大到小排序
})
返回值:排序后的数组
7. splice()//从指定位置添加或删除数据
语法1:数组名.splice(开始索引,删除个数)
语法2:数组名.splice(开始索引,删除个数,要插入的数据1、数据2...)
返回值:被删除的数据
8. concat()//进行数组的拼接,会把括号内数据和数组拼接为一个数组
语法:数组名.concat(数据1,数据2...)
返回值:拼接后的数组
9. join()//利用连接符将数组中数据连接成一个字符串
语法:数组名.join("连接符")
连接符不写,默认连接符为逗号(",")
返回值:连接符连接后的字符串
10. slice()//截取指定索引的数组(包前不包后)
语法:数组名.slice(开始索引,结束索引)
返回值:截取到的新数组
注意:只写开始索引,则截取到最后
开始和结束都不写,则从头到位把数组复制一遍
写负索引的话则索引从右往左,从-1、-2依次递减
11. indexOf()//从左到右查找该数据
语法1:数组名.indexOf(数据)//从左到右查找该数据,第一次出现的索引
语法2:数组名.indexOf(数据,开始索引)//从开始索引位置向右查找该数据,第一次出现的索引(包含开始索引)
返回值:查找到则返回索引,未找到则返回-1
12. lastIndexOf()//从右到左查找该数据
与indexOf()相同,查找方向相反
修改原始数组 | 不修改原始数组 |
---|---|
push() 末尾追加 | concat(数据1,数据2) 拼接 |
pop() 末尾删除 | join(“连接符”) 连接符连接成一个字符串 |
unshift() 开始添加 | slice(开始索引,结束索引) 截取(包前不包后) |
shift() 开始删除 | indexOf(数据,开始索引) 从左到右查找该数据 |
reverse() 反转 | lastIndexOf(数据,开始索引) 从右到左查找该数据 |
sort() 排序 | |
splice(开始索引,删除个数,插入数据) 指定位置添加或删除数据 |
1.核心思想:拿数组中相邻的两个数字作比较,如果要进行从大到小排序,把大的向后放置接口。
2.代码实现
var arr = [10, 12, 31, 4, 5, 16]
for (var i = 0; i < arr.length - 1; i++) {
for (var j = 0; j < arr.length - 1 - i; j++) {
var temp = arr[j];
if (arr[j] > arr[j + 1]) {
arr[j] = arr[j + 1]
arr[j + 1] = temp
}
}
}
1.核心思想:找到该数组最小的数据,定义一个变量min记录最小数据的索引,将最小数据和索引为0的数据进行位置交换,这样索引为0的便是最小的数据。依次类推,下次找到最小索引数据和1交换位置...
2.代码实现
arr = [77, 8, 452, 53, 76, 98, 95, 76, 9]
for (var j = 0; j < arr.length - 1; j++) {
var min = j
for (var i = j + 1; i < arr.length; i++) {
if (arr[min] > arr[i]) {
min = i
}
}
var temp = arr[j]
arr[j] = arr[min]
arr[min] = temp
}
1.概念:当从数组中删除某一个数据之后,从删除的数据开始之后的数据的索引都会向前递进。
2.解决方案:在递增之前递减,使索引保持不变
3.数组去重思想1:改变原数组
先拿一个数据和其他数据比较,如果有相同的则,删掉后面的。
4.数组去重代码1:
方法1:
var arr = [100, 100, 200, 200, 300, 400, 300, 400]
for (var i = 0; i < arr.length - 1; i++) {
for (var j = 1; j < arr.length; j++) {
if (arr[i] == arr[j]) {
arr.splice(j,1)
j--
}
}
}
方法2:
for (var i = 0; i <= arr.length; i++) {
var index = arr.indexOf(arr[i], i + 1)
if (index != -1) {
arr.splice(index, 1) //删除查询到的索引位置数据
i--
}
}
5.数组去重思想2:不改变原数组
创建一个空数组,遍历旧数组中的数据挨个添加到新的数组中,在加入新数组前进行判断(如果新数组中有该数据,则不加,没有,则加入)
6.数组去重代码2:
var arr = [100, 100, 200, 200, 300, 400, 300, 400]
var newArr = []
for (var i = 0; i < arr.length; i++) {
if (newArr.indexOf(arr[i]) == -1) {
newArr.push(arr[i])
}
}
6.数组去重代码3://利用Set集合,自身会去重
var set = new Set([12,12,43,34])//伪数组
Array.from(set)//伪数组转数组
Array.from(new Set(arr))
不改变原始数组
1. forEach()//用于遍历数组
语法:数组名.forEach(function(item,index,origin) {
可以写三个形参:
第一个形参是用来表示数组中的数据,一般建议起名为item
第二个形参是用来表示数组的索引,一般建议起名为index
第三个形参是用来表示原始数组的,一般建议起名为origin
})
2. map() //对数组中的数组进行加工处理,映射成一个新的数组
语法:数组名.map(function(item,index,origin) {
加工的语句需要写在return之后
return 加工语句
})
返回值:加工后的新数组
3. filter()//过滤数组
语法:数组名.filter(function(item,index,origin)) {
return 过滤条件
}
返回值:过滤后的新数组
4. find()//查找满足条件的第一项数据
语法:数组名.find(function(item,index,origin)) {
return 查找条件
}
返回值:查找到的数据,未找到则为undefined
5. findIndex()//查找满足条件的第一项数据的索引
语法:数组名.find(function(item,index,origin)) {
return 查找条件
}
返回值:查找到的数据的索引,未找到则为-1
6. every()//判断数组中的每一个数据是否都满足条件 类似于&&
语法:数组名.every(function(item,index,origin)) {
return 判断条件
}
返回值:都满足则为true,反之则为false
7. some()//判断数组中的每一个数据是否都满足条件 类似于 ||
语法:数组名.every(function(item,index,origin)) {
return 判断条件
}
返回值:有一个满足则为true,都不满足则为false
8. reduce() //数组里数据累加
语法1:数组名.reduce(function(prev,item,index,origin){
第一个形参表示初始值,或上一次求和结果一般起名prev
return prev+item
})
//数组里数据相加和
语法2:数组名.reduce(function(prev,item,index,origin){
第一个形参表示初始值,或上一次求和结果一般起名prev
return prev+item
},初始值)
//初始值加上数组里数据和
返回值:求和结果
item/*每一个数据*/ index/*索引*/ origin//原始数组
不改变原始数组 | |
---|---|
forEach() 遍历 | findIndex() 查找数据索引 |
map() 加工(映射) | every() 判断数据是否满足条件(都要满足&&) |
filter() 过滤 | some() 判断数据是否满足条件( 一个满足即可|| ) |
find() 查找数据 | reduce() 求和 (prev:初始值) |
1. random() //获取随机数
语法:Math.random()
返回值:产生0-1的随机小数//(包前不包后)
2. round(数字) //四舍五入
语法:Math.round()
返回值:四舍五入取整后的结果
3. ceil(数字) //向上取整
语法:Math.ceil()
返回值:向上取整后的结果
4. floor(数字) //向下取整
语法:Math.floor()
返回值:向下取整后的结果
5. abs(数字) //求绝对值
语法:Math.abs()
返回值:返回一个正数
6. pow(数字1,数字2) //幂运算
语法:Math.pow(x,y)//x的y次方 等价于x**y
返回值:返回幂运算结果
7. sqrt(数字) //求该数的算数平方根
语法:Math.sqrt()
返回值:算数平方根结果
8. max(数字1,数字2,数字3) //求最大值
语法:Math.max()
返回值:返回最大值
9. min(数字1,数字2,数字3) //求最小值
语法:Math.min()
返回值:返回最小值
10. Math.PI //Math的属性 π
随机数公式:Math.round(Math.random() * (max-min) + min) //求min--max的随机数:
//随机索引时 Math.round(Math.random() * (arr.length - 1)) (arr.length-1)是一个整体要括号包起来
// 方法1、利用随机数公式随机出一个颜色值(rbg方式)
var r = Math.round(Math.random() * 255)
var g = Math.round(Math.random() * 255)
var b = Math.round(Math.random() * 255)
var div = document.querySelector('div')
div.style.background = `rgb(${r},${g},${b})`
// 方法2、利用随机数公式随机出一个颜色值(16进制方式)
var arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'a', 'b', 'c', 'd', 'e', 'f']
var color = '#'
for (var i = 0; i < 6; i++) {
color += arr[Math.round(Math.random() * (arr.length - 1))]
}
var p = document.querySelector('p')
p.style.background = color
// 扩展
1. toString() //将十进制转换成其他进制的方法
语法:十进制数字.toString(进制)
例: a = 15 a.toString(2) //将a=7转换为2进制 1111
a = 15 a.toString(8) //将a=7转换为2进制 17
a = 15 a.toString(16) //将a=7转换为2进制 f
2. parseInt() //与toString()相反,将其他进制数字,转换为十进制
语法:parseInt(数字,你要把这个数字当成几进制)
返回值:将数字以十进制形式
3. toFixed() //保留几位小数
语法:数字.toFixed(要保留几位小数)
返回值:保留小数后的字符串,会进行四舍五入
// 方法3、利用随机数公式随机出一个颜色值(16进制方式)
var color = '#'
for (var i = 0; i < 6; i++) {
color += Math.round(Math.random() * 15).toString(16)
}
var p = document.querySelector('p')
p.style.background = color
1. 创建字符串:
方法1:字面量方式
var 变量名 = ''
方法2:内置构造函数方式
var 变量名 = new String()
2. 引号的区别:"" '' ``
单引号和双引号没有区别
反引号(也叫模板字符串)则不同
区别:1)单双引号不支持换行书写,而反引号支持
2)单双引号不识别变量,而反引号支持
识别变量的语法:${变量}
3. 字符串即是基本数据类型,也是引用数据类型
包装类型://引用数据类型,有属性和方法:String、Boolean、Number
存储时属于基本数据类型
在调用属性和方法时,会转为引用数据类型
使用完毕属性和方法后,会转为基本数据类型
3.字符串的基本操作:
3.1:字符串的长度(引号里有几个字符,长度就是几)
字符串的length是一个只读属性,不能设置
语法:字符串.length
空格也算字符
3.2:字符串的索引
索引从左到右从0开始依次+1
只能通过索引获取对应的字符,不能进行修改设置
语法:字符串[索引]
3.3:遍历字符串
for (var i = 0; i < str.length; i++) {
str[i]
}
JSON字符串:只有属性,没有方法。//遵循外单引号,内双引号(数字可以不使用""包裹)
JSON字符串==>对象:JSON.parse(str字符串)
JSON对象==>字符串:JSON.stringify(obj)
1.charAt() //找到指定索引的字符
语法:字符串.charAt(索引)
返回值:返回索引对应的字符//不存在则返回空字符串
如果用str.[索引]找对应字符,索引不存在结果为undefined
2.charCodeAt() //找到指定索引字符的编码
语法:字符串.charCodeAt(索引)
返回值:返回索引对应的字符的编码,不存在则返回NaN
3.toUpperCase() //将字符串里字母转换为大写
语法:字符串.toUpperCase()
返回值:转换为大写的字符串
4.toLowerCase() //将字符串里字母转换为小写
语法:字符串.toLowerCase()
返回值:转换为小写的字符串
5.substr() //截取,开始索引截取几个
语法:字符串.substr(开始索引,个数)
不写参数是截取全部,相当于复制
只写开始索引,不写个数,是截取至末尾
返回值:截取到的字符串
6.substring() //截取,开始索引至结束索引(不支持写负数)
语法:字符串.substring(开始索引,结束索引) //包前不包后
返回值:截取到的字符串
7.slice() //截取,开始索引至结束索引(支持写负数)
语法:字符串.slice(开始索引,结束索引) //包前不包后
返回值:截取到的字符串
8.split() //按照分隔符拆分字符串为数组
语法:字符串.split('分隔符')
返回值:拆分后的数组
9.concat() //拼接字符串
语法:字符串.concat(字符串1,字符串2...)
返回值:拼接后的字符串
10.indexOf() //从左到右查找指定字符
语法:字符串.indexOf(要查找的字符,开始索引)
返回值:找到的第一个字符的索引,没找到则-1
11.lastIndexOf()//从右到左查找指定字符
语法:字符串.indexOf(要查找的字符,开始索引)
返回值:找到的第一个字符的索引,没找到则-1
12.includes() //查找指定字符
语法:字符串.includes(字符串片段)
返回值:找的则为true,没找到则为false
13.startsWith() //检测是否以某字符开头
语法:字符串.startWith(字符串片段)
返回值:以指定字符串开头则true,反之false
14.endsWith() //检测是否以某字符结尾
语法:字符串.startWith(字符串片段)
返回值:以指定字符串结尾则true,反之false
15.trim() //去除字符串首尾的空格
语法:字符串.trim()
返回值:去除空格后的字符串
16.trimStart()或trimLeft() //去除开头的空格
语法:字符串.trimStart()
返回值:去除开头空格后的字符串
17.trimEnd()或trimRight() //去除末尾的空格
语法:字符串.trimEnd()
返回值:去除末尾空格后的字符串
18.replace() //可以替换字符串中的某一小段字符
语法:字符串.replace(旧字符,新字符)//使用新的替换第一个旧的
返回值:替换后的字符串
19.repeat() //让字符串重复几次
语法:str.repeat(次数)
返回值:重复几次后的字符串
不改变原字符串 | ||
---|---|---|
charAt() 查指定索引字符 | slice() 截取至结束索引(支持负数) | startsWith() 是否以开头 |
charCodeAt() 查指定索引字符编码 | split() 分隔符转数组 | endsWith() 是否以结尾 |
toUpperCase() 字母转大写 | concat() 拼接字符串 | trim() 去除首位空格 |
toLowerCase() 字母转小写 | indexOf() 左到右查字符,无则-1 | trimStart()或trimLeft() 去左侧空格 |
substr() 截取几个 | lastIndexOf() 右到左查字符,无则-1 | trimEnd()或trimRight() 去右侧空格 |
substring() 截取至结束索引(不能负数) | includes() 查指定字符,无则false | replace() 新换旧 |
1. ASCII:在这个表中有很多字符对应的编码,这个编码是一个数字
例: 大写A:65 小写a:97 空格:32
1000毫秒 = 1秒
语法1: var 变量名 = new Date() //可以得到当前的系统时间。括号里不写内容
语法2: var 变量名 = new Date()//括号里写内容,创建指定日期的时间对象
1)写数字:数字可写多个,通过逗号隔开
一个数字代表毫秒数,会从1970-01-01 0时0分0秒,再加上时区,加上写的时间
一个以上的数字时,则依次为:年 月 日期 时 分 秒 //月份用数字表示时(0表示一月依次递增)
2)写字符串
var 变量名 = new Date('年-月-日 时:分:秒')//字符串方式(1月就是1月)
var 变量名 = new Date('年/月/日 时:分:秒')
1.获取:get
1)获取年:时间对象.getFullYear()
2)获取月份:时间对象.getMonth()
3)获取日期:时间对象.getDate()
4)获取时:时间对象.getHours()
5)获取分:时间对象.getMinutes()
6)获取秒:时间对象.getSeconds()
7)获取毫秒:时间对象.getMilliSeconds()
8)获取时间戳:时间对象.getTime() //从1970年1月1日 0时0分0秒 至当前时间的差值,差值为毫秒
9)获取星期:时间对象.getDay() //星期中0表示星期天,1表示周一
2.设置:set
1)设置年:时间对象.setFullYear()
2)设置月份:时间对象.setMonth()
3)设置日期:时间对象.setDate()
4)设置时:时间对象.setHours()
5)设置分:时间对象.setMinutes()
6)设置秒:时间对象.setSeconds()
7)设置毫秒:时间对象.setMilliSeconds()
3.获取时间字符串
1)获取年月日:时间对象.toLocaleDateString() //年月日之间使用/连接
2) 获取时分秒:时间对象.toLocaleTimeString()
3)获取年月日 时分秒: 时间对象.toLocaleString()
两个时间可以直接相减//的到的值为毫秒数,需要转换
var d1 = new Date()
var d2 = new Date('2023-1-21 00:00:00')
var cha = (d2 - d1) / 1000 //转为秒数
var day = parseInt(cha / 60 / 60 / 24) //天
var hours = parseInt(cha / 60 / 60 % 24) //时
var minutes = parseInt(cha / 60 % 60) //分
var seconds = parseInt(cha % 60) //秒
console.log(`距除夕还有${day}天${hours}时${minutes}分${seconds}秒`)
1.延迟定时器:
语法:setTimeout(函数,数字)
写的数字就是时间,单位为毫秒//意思是延迟多久执行函数里的代码
返回值:一个数字//表示这是第几个定时器
2.间隔定时器(循环定时器):
语法:setInterval(函数,数字)
写的数字就是时间,单位为毫秒//意思是每间隔多少秒执行一次
返回值:一个数字//表示这是第几个定时器
3.停止定时器
1) clearTimeout()
2)clearInterval()
//括号里写你要停止的定时器的返回值,两种语法都可以清除任意一种定时器
4.倒计时小demo
function getTime(d1, d2) {
var cha = (d2 - d1) / 1000 //转为秒数
//判断一下,如果时间为0,则停止定时器
if (cha <= 0) {
clearInterval(timer)
return
}
var day = parseInt(cha / 60 / 60 / 24) //天
var hours = parseInt(cha / 60 / 60 % 24) //时
var minutes = parseInt(cha / 60 % 60) //分
var seconds = parseInt(cha % 60) //秒
return `距除夕还有${day}天${hours}时${minutes}分${seconds}秒`
}
var d1 = new Date()
d2 = new Date('2023-1-6 14:47:00')
document.body.innerHTML = getTime(d1, d2)
var timer = setInterval(function() {
d1 = new Date()
d2 = new Date('2023-1-6 14:47:00')
document.body.innerHTML = getTime(d1, d2)
}, 1000)
(browser object model )浏览器对象模型
bom的常用方法,统一语法都是window.XXX
但是window可以省略
1.提示框(弹出框)
语法:window.alert('提示文本')
表现形式:一个提示文本+一个确定按钮
返回值:undefined
2.询问框
语法:window.confirm('提示文本')
表现形式:一个提示文本+确定+取消按钮
返回值:点确定返回true,取消false
3.输入框:
语法:window.prompt('提示文本')
表现形式:提示文本+文本输入框+确定+取消
返回值:点确定返回用户输入的文本,取消null
//注意点:以上三个框有一个共同特点,就是会阻止程序的执行(用户不点击按钮,程序不往下执行)
概念:可以看见的区域的大小
获取宽度:window.innerWidth
获取高度:window.innerHeight
注意:获取到的值不带单位,获取到的宽高会包括滚动条
1.load事件:加载事件
语法:window.onload = function() {}
触发条件:当页面内所有的外部资源(比如html、css、js、图片、视频、音频等)全部加载完毕之后触发
2.resize事件
语法:window.onresize = function(){}
触发条件:当页面(窗口)的尺寸发生改变时就触发
3.scroll事件
语法:window.onscroll = function(){}
触发条件:只要页面滚动了就会触发
//事件只要触发,就会自动执行function里的代码
1、location对象
语法:window.location
2、location对象里有一个href属性,可以通过这个属性来获取页面的网址
获取语法:window.location.href
设置语法:window.location.href = 值//重新赋值,改变网址,实现网页跳转的效果(是在当前页面进行跳转的)
3、location对象里有一个方法reload()//刷新网页
语法:window.location.reload()
//需要通过绑定别的事件使用,直接写会造成一直刷新的死循环状态
1、打开网页
语法:window.open('地址')//打开一个网页(是在新窗口打开的)
2、关闭网页
语法:window.close()//关闭当前页面(模仿关闭按钮)
获取浏览器卷去的尺寸
1.获取浏览器卷去的高度
语法1:document.documentElement.scrollTop//有doctype标签时使用
语法2:document.body.scrollTop//没有doctype标签时使用
兼容语法:
var 变量 = document.documentElement.scrollTop || document.body.scrollTop
2.获取浏览器卷去的宽度
语法1:document.documentElement.scrollLeft//有doctype标签时使用
语法2:document.body.scrollLeft//没有doctype标签时使用
兼容语法:
var 变量 = document.documentElement.scrollLeft || document.body.scrollLeft
语法1:window.scrollTo(x,y)
x横向位置,y纵向位置,x,y值不用带单位//x和y必须都写,否则会报错
语法2:
window.scrollTo({left:XXX,top:XXX,behavior:'smooth'})
left横向位置,top纵向位置,behavior:'smooth'实现平滑过度效果//可以单独写一个方向,只移横向或纵向
浏览器的历史记录:window.history
再window.history里有三个方法,可以模拟前进、后退、刷新
1、前进://可以去到下一个历史记录
语法:window.history.forward()
2、后退://可以去到上一个页面
语法:window.history.back()
3、刷新(前进、回退)://可以模拟前进、回退、刷新
语法:window.history.go(数字)
写正数:就是前进,数字是几就前进几步 写负数:就是回退,数字是几就回退几步
写0:就是刷新
1.获取可视窗口的尺寸:
window.innerWidth、window.innerheight
2.获取页面(浏览器)卷去的高度和宽度:
var 变量 = document.documentElement.scrollTop || document.body.scrollTop
var 变量 = document.documentElement.scrollLeft || document.body.scrollLeft
3.实现网页跳转:
window.open('地址')//打开一个网页(是在新窗口打开的)
设置语法:window.location.href = 值//(是在当前页面进行跳转的)
4.如何模拟刷新网页:
window.location.reload()
window.history.go(0)
5.如何模拟关闭按钮:
window.close()
6.如何模拟前进:
window.history.forward()
window.history.go(正数)
7.如何模拟回退:
window.history.back()
window.history.go(负数)
8.设置浏览器的滚动位置:
window.scrollTo()
9.浏览器中的常见事件:
加载事件:window.onload = function() {}
页面尺寸改变事件:window.onresize = function(){}
页面滚动事件:window.onscroll = function(){}
(document object model) 文档对象模型
1.标签分类:
非常规元素:html、head、body
剩下的都是常规标签
2.非常规元素的获取:
html:document.documentElement
head:document.head
body:document.body
3.常规元素的获取:
1)document.getElementById('id名')
返回值:查找到的元素,找不到为null
2)document.getElementsByClassName('class名')
返回值:一个伪数组,如何想要操作标签,需要通过索引获取,不能直接操作,找不到则为空数组
//可以遍历,但有些常用方法不可用
3)document.getElementsByTagName('标签名')
返回值:伪数组,如何想要操作标签,需要通过索引获取,不能直接操作,找不到则为空数组
//可以遍历,但有些常用方法不可用
4)document.querySelector('选择器')//根据选择器,找到符合条件的第一个标签
返回值:查找到的元素,找不到为null
5)document.querySelectorAll()//根据选择器找到符合条件的所有标签
返回值:伪数组,如何想要操作标签,需要通过索引获取,不能直接操作,找不到则为空数组
1.获取样式
获取行内样式:
语法:元素.style.样式名
获取非行内样式:
语法:window.getComputedStyle(元素).样式名//window可以不写
2.设置样式
语法:元素.style.样式名 = 值//只要通过js设置样式,该样式都会设置成行内样式
1.元素的属性:只要在标签名之后的单词称为属性
2.属性的分类:原生属性、自定义属性、h5自定义属性
1)原生属性:就是w3c标准中存在的属性,比如class,id,src,alt等
2)自定义属性:就是标准中没有的,我们自己写的,对标签不会产生影响,用来记录信息的
3)h5自定义属性:因为自定义与原生不好区分,所以规定写自定义属性最好以data-开头,data-后面的才是属性名字(没有特殊含义,只是为了和原生区分开来)
3.操作原生属性:
获取原生属性的属性值:
语法:元素.属性名
操作原生属性的属性值:
语法:元素.属性名= 值
4.操作自定义属性:
获取自定义属性:
语法:元素.getAttribute('属性名')
设置自定义属性:
语法:元素.setAttribute('属性名','属性值')
//属性名已存在则是修改,不存在是添加
删除自定义属性:
语法:元素.removeAttribute('属性名')
5.操作H5自定义属性:
获取H5自定义属性:
语法1:元素.dataset.属性名
语法2:元素.dataset['属性名']
设置H5自定义属性的值
元素.dataset.属性名 = '值'
元素.dataset.[属性名] = '值'
删除H5自定义属性
delete 元素.dataset.属性名
delete 元素.dataset[属性名]
1.方式1:
1)获取类名:
语法:元素.className()
//会得到所有的类名,是一个字符串类型,想要得到单个类名,则需要字符串拆分
2)设置类名:
语法:元素.className = 值
//注意:会将之前的类名,完全覆盖成设置的名字。需要添加的话需要用+=,做字符串拼接
2.方式2:
1)获取类名:
语法:元素.classList[索引]
2)添加类名:
语法:元素.classList.add(类名)
3)删除类名:
语法:元素.classList.remove(类名)
4)切换类名:
语法:元素.classList.toggle(类名)//有就删,无就加
1.获取内容://只可以获取双标签
语法1:元素.innerText//获取元素下的所有文本
语法2:元素.innerHTML//获取元素下的所有标签和文本
2.添加内容://只可以给双标签添加内容
语法1:元素.innerText = 内容//不识别标签
语法2:元素.innerHTML = 内容//识别标签
//都会覆盖原先内容 ,想要原先内容保留需要写成+=拼接
3.value//专门用于操作表单元素
获取:表单元素.value
操作:表单元素.value = 内容
1.this://意思 就是这个
用的点击事件中,this指你点击的那个元素(点击谁,谁就是this)
2.js中让复选框选中:input.checked = true
js中让复选框取消选中:input.checked = false
1.获取元素:
document.getElementById('id') //第一个
document.getElementsByClassName('类名') //多个
document.getElementByTagName('标签名') //多个
document.querySelect('选择器') //第一个
document.querySelectAll('选择器') //多个
2.操作元素:
1)操作标签的样式:
获取:
元素.style.样式名 //行内样式
getComputedStyle(元素).样式名 //非行内样式
设置:元素.style.样式名
2)操作标签的属性:
获取:
元素.属性名 //原生属性
元素.getAttribute('属性名')//自定义属性
元素.dataset.属性名 元素.dataset['属性名']//H5自定义属性
设置:
元素.属性名 = 值 //原生属性
元素.setAttribute('属性名','属性值')//自定义属性
元素.removeAttribute('属性名')//删除自定义属性
元素.dataset.属性名 = '值' 元素.dataset.[属性名] = '值'//H5自定义属性
delete 元素.dataset.属性名//删除H5自定义属性
3)操作标签的类名:
获取:
元素.className //需要字符串拆分才可获得单独类名
元素.classList[索引]
设置:
元素.calssName = '类名' //会覆盖原类名, += ' 类名'可实现拼接类名
元素.classList.add('类名')
元素.calssList.remove('类名') //删除指定类名
元素.classList.toggle('类名') //有删,无加
4)操作标签的内容:
获取:
元素.innerText //元素下所有文本
元素.innerHTML //元素下所有文本和标签
添加:
元素.innerText = 内容 //不识别标签
元素.innerHTML = 内容 //识别标签
//都会覆盖原内容,想保留需+=
value://专用于表单
获取:表单元素.value
操作:表单元素.value = 内容
5)this:谁指向它,它就是谁//例:点击的是谁,this就是谁
先定义一个变量flag=true //门开着
当执行代码时让flag=false //关门
当代码执行完毕后让flag=true //开门
这样就可以保证只有代码执行完毕才可以再次进入该程序 //只有当你事干完开门后,别人才可以再进来
//获取验证码小demo
var btn = document.querySelector('button')
var flag = true
btn.onclick = function() {
if (flag === false) return
flag = false
var num = 5
btn.innerHTML = `还有${num}秒`
var timer = setInterval(function() {
num--
btn.innerHTML = `还有${num}秒`
if (num === 0) {
clearInterval(timer)
btn.innerHTML = '获取验证码'
flag = true
}
}, 1000)
}
先清除所有样式,再给当前元素添加样式
方式1:
语法:
元素.offsetWidth
元素.offsetHeight
//获取的标准盒宽高尺寸:width+border+padding
//获取的怪异盒宽高尺寸:width
方式2:
语法:
元素.clientWidth
元素.clientHeight
//得到的是该元素:width+padding的尺寸
1. 元素.offsetParent //得到该元素有定位的父级元素(参照物)
2.获取偏移值:
方式1:
语法:
元素.offsetLeft
元素.offsetTop
//获取的结果是相对于参照物左边或上边的距离(获取到的结果是不带单位的,是一个数字)
方式2:
语法:(了解,几乎不用)
元素.clientLeft
元素.clientTop
//获取的结果是内容和内间距之和与元素边线的距离(得到的就是边框线的粗细)
BOM的语法:
获取宽度:window.innerWidth
获取高度:window.innerHeight
//得到的宽高包含滚动条
DOM语法:
获取宽度:document.documentElement.clientWidth
获取高度:document.documentElement.clientHeight
//得到的宽高不包含滚动条
瀑布流:先渲染一部分数据,然后页面滚动到底部时再加载一部分数据
判断是否滚动到底部:
公式:可视窗口的高度+页面卷去的高度 > main元素的高度+main元素的偏移量
1.概念:把html页面看成一个倒立的树状的结构,一般叫dom树,dom节点就是dom树中的一个元素
2.Dom节点的分类:
1)元素节点:就是页面上的每一个标签
2)文本节点:所有的文本内容,包含换行和空格
3)属性节点:就是标签上的属性
4)注释节点:页面上的注释,包含换行和空格
1.之前学习的获取元素节点的方式:
document.getElementById('id')
document.getElementsByClassName('类名')
document.getElementByTagName('标签名')
document.querySelect('选择器')
document.querySelectAll('选择器')
2.新的获取节点方式(包括但不限于元素节点)
1)//得到某元素下所有子节点(包括所有节点)
元素.childNodes
//返回值:一个伪数组,里面包含找到的所有子节点
2)//得到某元素下所有子节点(包括所有节点)
元素.children
3)//得到该元素下的第一个(最后一个)子节点
元素.firstChild
元素.lastChild
4)//得到该元素下的第一个(最后一个)子元素节点
元素.firstElementChild
元素.lastElementChild
5)//得到该元素的上一个(下一个)兄弟节点
元素.previousSibling
元素.nextSibling
6)//得到该元素的上一个(下一个)兄弟元素节点
元素.previousElementSibling
元素.nextElementSibling
7)//得到该元素的父节点(最大的父节点是document,html上级是document,再上级是null)
元素.parentNode
8)//得到该元素的父元素节点(最大的父元素节点是html,再上级是null)
元素.parentElement
9)//得到所有的属性节点
元素.attributes//返回一个对象(没有属性,则为空对象)
1.创建元素节点
语法:document.createElement('标签名')
2.创建文本节点
语法:document.createTextNode('文本内容')
//创造好的东西不会显示在页面上
语法:
父元素.appendChild(子节点)//将子节点追加到父元素最后
父元素.insertBefore(子节点,插入到谁的前面)//添加节点至谁前面
语法:
父节点.removeChild(子节点)//把子节点从父节点下删除
节点.remove()//删除自己
语法:
父节点.replaceChild(新节点,老节点)
语法:
节点.cloneNode(参数)//把节点复制一份
参数写true则,复制自己和后代
参数写false为只复制自己(默认值)
1)nodeType:节点属性,可以通过数字判断你的节点类型//返回值:一个数字
元素节点:1
属性节点:2
文本节点:3
注释节点:8
2)nodeName:节点名称
元素节点:大写的标签名称
属性节点:属性名字
文本节点:#text
注释节点:#comment
3)nodeValue:节点内容
元素节点:null
属性节点:属性值
文本节点:文本内容(包含换行和空格)
注释节点:注释内容(包含换行和空格)
同步代码:从上到下依次执行
异步代码:定时器、事件
代码执行过程://先执行同步代码,最后执行异步代码
1、概念:
事件:为了捕获用户的行为,根据用户的行为来做出一些相应的事情。//事件有其特定的触发条件
事件三要素:
1)事件源(绑定在谁身上的事件)
2)事件的类型(点击还是划过...)
3)事件处理函数//行为发生时,需要执行什么
2、绑定事件:
方式一:dom 0级 绑定
语法:事件源.on事件类型 = 事件处理函数
特点:同一个事件源的同一事件类型只能绑定一个事件处理函数//绑定多个后者会覆盖前者
方式二:dom 2级 绑定(事件监听)
标准浏览器:
语法:事件源.addEventListener(事件类型,事件处理函数)
特点:同一个事件源的同一事件类型可以绑定多个事件处理函数//顺序绑定,顺序执行
IE低版本浏览器:
语法:事件源.attachEvent('on事件类型',事件处理函数)
特点:同一个事件源的同一事件类型可以绑定多个事件处理函数//顺序绑定,倒序执行
3、事件解绑:
dom 0级 绑定
语法:事件源.on事件类型 = null
dom 2级 绑定(事件监听)
标准浏览器:
语法:事件源.removeEventListener('事件类型',要绑定的事件处理函数)
IE低版本浏览器:
语法:事件源.detachEvent('on事件类型',要绑定的事件处理函数)
1.鼠标事件
1)click//鼠标左键单击
2)dblclick//鼠标左键双击(300ms内2次点击就会触发)
3)contextmenu//鼠标右键单击
4)mousedown//鼠标按键按下
5)mouseup//鼠标按下抬起
6)mousemove//鼠标移动,只要移动就触发,大概1s触发60次左右
7)mouseover//鼠标移入,子元素会触发
8)mouseout//鼠标移出,子元素会触发
9)mouseenter//鼠标移入,子元素不会触发
10)mouseleave//鼠标移出,子元素不会触发
2.键盘事件//一般键盘事件绑定选择绑定在window、document、表单元素等可选元素上
1)keydown//只要是键盘上的按键按下了,都会触发。
2)keyup//只要是键盘抬起了,就会触发
3)keypress//键盘键入事件
//注意1:按下的按键真的会出现对应的文本内容,比如按abcd等就可以,按上下左右就不行。但是回车键可以触发。
//注意2:按下的内容必须和出现的内容一致(切换到中文之下是不行的)。
3.表单事件
1)focus//表单聚焦事件(得到焦点就触发)
2)blur//表单失焦事件(失去焦点就触发)
3)change//表单内容改变事件(聚焦和失焦的时候内容不一致就会触发)
4)input//表单输入事件(实时触发,只要是输入或者删除内容就会触发)
5)submit//表单提交事件(只有form才有提交行为,所以需要绑定给form) 配合return false
6)reset//表单重置事件,只有form才会有重置行为,所以绑定给form)
4.触摸事件//在移动端或者电脑屏幕可触摸的设备上才能执行
1)touchstart//开始触摸(手指接触到屏幕的瞬间)
2)touchmove//触摸移动(手指在屏幕上滑动,实时触发)
3)touchend//触摸结束(手指离开屏幕的瞬间)
5.拖拽事件
//拖拽行为有可能关联2个元素
拖拽元素(你正在拖着的元素)
拖放元素(你将要松手的时候放置的元素)
该元素需要可被拖拽,才能触发
如何让一个元素可被拖拽?(给元素设置一个draggable属性,值为true)
1)dragstart//开始拖拽(即将进入拖拽移动状态的瞬间)
2)drag//拖拽移动(实时触发,移动的时候)
3)dragend//结束拖拽(拖拽元素放手的时候触发)
============================
4)dragenter//拖拽元素进入拖放元素范围的时候触发(光标进入才触发)
5)dragleave//拖拽元素离开拖放元素范围的时候触发(光标离开才算)
6)dragover//拖拽元素进入拖放元素范围内了(实时触发)
7)drop//拖拽元素在拖放元素内放手的时候就触发(前提:需要在dragover内阻止默认行为才可,阻止默认行为语句:return false)
6.其他事件
1)selectstart//开始框选,可以绑定给document,在这个事件内写一个return false就可以实现阻止复制。
2)visibilitychange//可视窗口的可视度发生改变,绑给document(窗口可见不可见)
3)unload//绑定给window,窗口关闭的时候就触发(可以存个数据)
案例:关闭之前存一次时间,打开再获取一次,可以弹框一个:距离上次见面?时间。
鼠标事件 | ||
---|---|---|
click //左键单击 | dblclick //双击 | contextmenu //右键单击 |
mousedown //按下 | mouseup //抬起 | mousemove //移动 |
mouseover //移入(子元素触发) | mouseout //移出(子元素触发) | mouseenter //移入(子元素不触发) |
mouseleave //移出(子元素不触发) |
键盘事件 | ||
---|---|---|
keydown //键盘按下 | keyup //键盘抬起 | keypress //键盘键入 |
表单事件 | ||
---|---|---|
focus //得到焦点 | blur //失去焦点 | change //内容改变 |
input //输入 | submit //提交 | reset //重置 |
方式一:storage方案
localStorage:本地永久性存储(只要不手动删除,数据会一直在)
语法:
存储:window.localStorage.setItem(key,value)
修改://如果存的键相同,则替换value
获取:window.localStorage.getItem(key)、
删除:window.localStorage.removeItem(key)
window.localStorage.clear()//清空
特点:
1.永久存储,不删,则会一直存储
2.支持跨页面通讯,可在其他页面同样获取到你存的数据
3.只能存字符串,不能存复杂数据类型
sessionStorage:
语法:
存储:window.sessionStorage.setItem(key,value)
修改://如果存的键相同,则替换value
获取:window.sessionStorage.getItem(key)、
删除:window.sessionStorage.removeItem(key)
window.sessionStorage.clear()//清空
特点:
1.临时存储,页面关闭就没了
2.支持跨页面通信,但要求必须要从当前页面跳转过去
3.只能存字符串,不能存复杂数据类型
localStorage和sessionStorage区别:
localStorage:永久存储,支持跨页面通讯
sessionStorage:是临时存储,虽然也支持跨页面,但必须是从本页面跳转,且在当前窗口打开
方式二:cookie方案
语法:
存储/获取:document.cookie = 'key = value'
手动设置过期时间:document.cookie = 'key = value;expires=' + 时间对象//过期时间会自动转为世界标准时间(需要转为东八区时间)
特点:
1.只能存字符串,不能存复杂数据类型
2.存储的数据大小有限,只能存4kb左右
3.会话级别的存储,浏览器关闭就没了。但可以设置过期时间
4.cookie的操作必须依赖服务器
//toGMTString() 将时间对象转为东八区时间
两种方式的区别:
1.cookie只能存4kb左右,storage可以存20M左右
2.前后端交互时,cookie的数据会随页面请求自动携带,storage的数据不会自动携带
3.cookie前后端都可操作,storage只能前端js操作
4.cookie默认是会话级,且可以设置过期时间,storage不可以手动设置过期时间
5.cookie有js时就有,storage是h5才出
1.概念:事件发生时,会产生一个东西叫:事件对象//会存储本次事件发生时产生的一些信息
2.获取事件对象:
在事件处理函数里写一个形参,该形参由浏览器自动赋值
事件源.onclick = function(e){//e就是事件对象
var e = e || window.event//IE兼容写法
}
1.获取事件对象中和鼠标相关的信息:
方式一:client:得到光标相对于'浏览器可视窗口'的左上角的坐标值
语法:事件对象.clientX 事件对象.clientY
方式二:page:得到光标相对于'文档流'左上角的坐标值
语法:事件对象.pageX 事件对象.pageY
方式三:offset:光标相对于'准确触发事件的元素'左上角的坐标值
语法:事件对象.offsetX 事件对象.offsetY
2.鼠标跟随案例
在css里写:pointer-events:none//阻止事件传入,谁抖给谁加
1)keyCode //可以得到你按下了哪个键(onkeydown 按下)
2)shiftKey //按下了shift键时返回true
3)ctrlKey //按下了ctrl键时返回true
4)altKey //按下alt键时返回true
5)metaKey(指的是window键) //按下win键时返回true
1.w3c规定事件如何传播:
2.阻止事件冒泡:e.stopPropagation
1.阻止事件的默认行为
e.preventDefault() //
return false //只能0级使用
利用冒泡的原理,将原本绑定在子元素的事件委托给父元素,可以使用e.target获取你具体点击的元素
this 是绑定事件的事件源
e.target 是触发事件的事件源
1.h5新增的dataset:任何元素都有这个属性,是对象//保存着该元素身上,所有的h5属性
获取语法:ele.dataset.h5属性名
设置语法:ele.dataset.属性名 = 值
2.数组高级方法见: //p 一、20.9
3.字符串:trim、includes、startSwith、endsWith... //见p 一、22.2
4.严格模式:'use strict'
作用:消除js中不严谨的地方,提高执行效率
比如变量未声明直接赋值...
使用:放在作用域的最顶端,那这个作用域的所有内容都会遵循严格模式
5.JSON转字符串和对象的方法//见p 一、22.1
6.改变函数的this指向
call
语法:函数名.call(this的指向改变成谁,参数...)
返回值:无
apply
语法:函数名.apply(this的指向改变成谁,[函数的参数])
返回值:无
bind
语法:函数名.bind(this的指向改变成谁,函数的参数列表)
返回值:返回一个this指向改变后的函数
1.事件处理函数:里面的this都指向,事件源
2.定时器函数:this指向了window
3.对象里的方法:this指向对象本身
4.普通函数:this指向window
5.箭头函数:this指向了上一级
1.新增的定义变量:let let和var的区别:
let 1.不可以在同一个作用域内定义相同的变量
2.不可以挂载在window
3.会形成作用域
4.会形成暂时性死区(先定义后使用)
5.不会预解析
var 1.可以在同一个作用域内定义相同的变量
2.可以挂载在window
3.不会形成作用域
4.会形成暂时性死区(后定义可以先使用)
5.会预解析
2.定义常量:const与let
相同点:
1.不可以在同一个作用域内定义相同的变量
2.不可以挂载的window
3.会形成作用域
4.会形成暂时性死区(先定义后使用)
5.不会预解析
不同点:
1.const值不可以被修改,let可以
2.const必须声明即赋值,let不需要
3.模板字符串:``反引号 //支持换行,能够识别使用${}包裹的变量
概念:匿名函数的简化
语法:div.onclick = ()=>{}
setInterval(()=>{},1000)
注意点:
1.当箭头函数的参数位置有且只有一个参数时,()就可以省去,例:
原:div.onclick = function(e){}
省略后:div.onclick = e=>{}
2.当箭头函数的参数位置有两个及以上参数时,()不可以省去
3.当箭头函数的函数体内只有一行代码时,{}可以省去
4.当箭头函数的函数体内只有一行代码,且有return时,{}和return必须删除(或都不删)
原:div.forEach(function(item){return 1;})
省略后:div.forEach(item=>1;)
5.箭头函数中没有this,它内部的this是该箭头函数所在作用域的this//向上一层找,直至找到非箭头函数的this
1.数组的解析赋值:
语法:var [a,b,c,d] = [12,43,543,432];//a,b,c,d对应数组中的数据
2.对象的解析赋值:
语法1:var {name,age} = {name:'zs',age:18};
语法2:var {name:x} = {name:'zs',age:18};//只取出name,并起别名为x
作用1:用于展开:
var arr = [1,2,3];
原:console.log(arr[0],arr[1],arr[2]);
现:console.log(...arr);
var newArr = [...arr,50]//相当于[1,2,3,50];
var obj1 = {name:'zs'};
var obj2 = {age:18}
var obj3 = {...obj1,...obj2};//相当于{name:'zs',age:18};
作用2:用于合并:
function fn(...ages){} //等价于function fn(a,b,c,d等)
ES6中键名和值名一样的话,可以只写一个:
var age = 'age'; var age = 'age';
var obj = {age} //相当于 var obj = {age:age};
概念:当不传参数时,使用的是默认参数
function(a=1){}
arguments //任何函数都有一个arguments,保存着所有的实参,伪数组(不常用)
1.模板字符串`${包裹变量}`
2.for...of 遍历数组的元素
3.class类//详见面向对象
1.set集合:类似于数组的数据结构,会自动去除重复元素//是伪数组
语法:var set = new Set(数组)
增:set.add()
删:set.delete()
查:set.has(元素) //判断是否含有这个元素 true/false
清空:set.clear()
长度:set.size
数组去重:Array.from(new Set(arr))
2.map集合:类似于对象的数据结构
语法:var map = new Map{};
增:map.set(key,value)
删:map.delete(key)
查:map.get(key)
清空:map.clear
for...of可以用于遍历集合
set遍历的是数据
map遍历的是键值对
1.一个功能一个js文件
2.模块化的好处:复用性提高,易维护,减少了命名冲突
3.导入语法:
<script src=""></script>//会发生命名冲突
//导入的是对象形式,同名也不会发生命名冲突
<script type="module">
import 模块名(自定义名) from './cart.js'
</script>
4.导出语法://导出的是对象形式
export default {
导出的内容
a:a,
fn:fn
}
5.注意点:
打开的时需要从服务器打开
1.给元素添加定位,通过改变元素的定位,完成元素的移动
1.面向过程编程:想要实现一个功能,找到实现的思路,分析完成该功能的步骤,按照步骤一步步来完成。
2.面向对象编程:想要实现一个功能,找到一个能帮助我们完成这个功能对象,让这个对象调用对象中的具体方法来进行的实现的。
3.面向对象的核心:封装、继承
1.var obj = {};//字面量法
2.var obj = new Object();//内置构造函数来创建
3.封装函数,批量创造对象//工厂模式创建对象
4.通过构造函数模拟类,通过这个类创建对象//ES3提出的,没有类的概念。
例:function 构造函数名(){
}
构造函数与普通函数的区别:
构造函数: 1.首字母大写,且要求是名词
2.调用:通过new来调用
3.this指向new出的对象本身
4.第一行有一个默认的this,this默认值为{},最后一行有个默认的return this
5.为了实例化出一个对象,通过这个对象来调用属性和方法来完成具体的功能。
普通函数: 1.驼峰命名,要求动词
2.直接调用
3.this指向window
4.默认return的是undefined
5.为了实现一个功能。
constructor属性:
5.class 类
1.用于解决构造函数每个实例调用方法时,需要单独开辟新地内存空间存储,造成的内存占用过大的问题。
2.解决思路:找一个对象,将这个方法放到这个对象上,只要实例化的对象可以访问到这个方法即可。
3.原型对象://任何构造函数都有一个原型对象(prototype属性),实例化的对象可以直接访问
获取:构造函数.prototype
使用:将方法放在原型对象上,这样每一个实例对象都可以访问这个原型对象,不需要重新开辟内存。
//prototype属性正好可以解决函数重复占用内外的问题
1.构造函数被实例化后都会有一个__proto__属性,指向了构造函数的prototype原型对象,所以对象才可以使用构造函数prototype原型对象的属性和方法。
对象的原型__proto__和构造函数prototype原型对象里都有一个constructor属性,constructor称为构造函数,指回了构造函数本身。
每一个对象都有一个__proto__属性,它指向了创建它的,构造函数的原型对象,原型对象也是一个对象,它也存在__proto__属性,这样一层层向上指向的规则形成了原型链。
在没有继承的情况下实例对象的原型对象指向的是Object的原型对象
1、 创建类
class 类名{
constructor(参数列表){
}
//方法写在这里,相当于放在了prototype原型上
}
2.注意点:
1)new 时会调用constructor构造函数
2)constructor构造函数的this指向是实例化出来的对象
3)在constructor平级的位置可以书写一个方法,这个方法就放在了该类的原型对象上
4)原型对象的方法里的this也指向实例化出来的对象
5)原型对象的方法可以直接访问构造函数的属性
6)构造函数中可以直接访问原型对象中的方法
概念:子类继承父类的属性和方法
原生继承:
1)借用父类构造函数继承:能够使子类继承到父类的属性
function Father(uname) {
this.uname = uname;
}
function Son(uname, age) {
Father.call(this, uname);
this.age = age;
}
2)原型继承:能够使子类继承到父类的方法
function Father(name) {
this.name = name;
}
Father.prototype.play = function () {
console.log('玩');
}
function Son() { }
Son.prototype = new Father();
let s = new Son();
s.play();
3)组合继承:(借用父类构造函数继承)+(原型继承)//子类继承父类的属性和方法
function Father(name) {
this.name = name;
}
Father.prototype.play = function () {
console.log('玩');
}
function Son(name, age) {
Father.call(this, name);
this.age = age;
}
Son.prototype = new Father();
Son.prototype.constructor = Son;
Son.prototype.sleep = function () {
console.log('吃饱就睡');
}
4)ES6继承:通过extends和super关键字
1.子类 extends 父类
2.子类使用 super(属性列表)访问父类//super做了调用父类的constructor、改变this指向
class Father {
constructor(name, age) {
this.name = name;
this.age = age;
}
eat() {}
}
class Son extends Father {
constructor(name, age, food) {
super(name, age);
this.food = food;
}
eat() {
console.log(this.name + '今年' + this.age + '岁,爱吃' + this.food);
}
}
特点: 1.函数嵌套函数
2.内部函数持有外部函数的局部变量
3.内部函数就是闭包
如何查看是否形成闭包:控制台打断点查看//closure
作用: 1.延长局部变量的生命周期
2.让局部变量持久保存在内存中
3.私有化变量的同时,防止全局变量污染
缺点: 1.内存泄漏、内存占用过大
函数柯里化的形式:把接受多个参数的函数,变成接受单一参数的函数,而且返回结果是新函数的技术,让新函数处理剩余参数。
好处:减少冗余,将代码变得简洁,参数可以实现复用。
//把形式一转化为形式二的过程叫做函数柯里化
//形式一
function getSum(a,b,c){
return function (){
return a + b + c;
}
}
//形式二
function getSum(a){
return function(b){
return function(c){
return a + b + c;
}
}
}
1.概念:在函数内部直接或间接的调用函数本身;
2.注意点:递归要有出口,没有出口就形成死递归
例:求n的阶乘
function jieC(n){
if(n==1){
return 1;
}else{
return n * jieC(n-1);
}
}
3.调用:
调用阶段:从外到里一层一层开辟新的空间
返回阶段:从里到外一层一层返回值
1.浅拷贝:复制了一份,相互之间会有影响
数组:
1).直接赋值
//下面只能实现单层深拷贝,对于多层是浅拷贝
2) slice(0)
3) concat()
4) ...扩展运算符
5) for遍历
...
对象:
1)直接赋值
//下面只能实现单层深拷贝,对于多层是浅拷贝
2) ...扩展运算符
3) for遍历
2.深拷贝:复制了一份,相互之间不会有影响
通过JSON.parse(JSON.stringify(obj))实现深拷贝。
for 循环加递归
1.参数:
参数一:为那个对象定义属性
参数二:什么属性
参数三:一个对象形式(两种类型:存取描述符,数据描述符)//二选一
2.语法:
Object.defineProperty(obj,'name',{
value:'zs', //对象name对应的值
writable:true, //表示对象的name属性是否可以被修改,默认是false
configurable:true, //表示对象的name属性是否可以被删,默认是false
enumerable:true //表示对象的name属性是否可以被遍历,默认是false
})
var obj = {};
var x = 1;
Object.defineProperty(obj,'name',{
get(val){//默认参数,值为你获取的值
return x;
},//有人读取name属性时就会触发get
set(val){//默认参数,值为你设置,或修改的值
x = value;
}//有人修改name属性时就会触发set
}
数据劫持:
数据代理:通过一个对象代理对另一个对象的操作(增、删、获取、设置)
vue2.0 使用Object.defineProperty() 有点问题 只有获取和设置
vue3.0 使用proxy 有获取、设置、增、删
//不直接对源对象进行操作,而是通过操纵代理对象,进行对原对象的增删改查
new Proxy(obj,{
get(target,prop){//参数一:代理的对象,参数二:访问的哪个属性
},
set(target,prop,val){//参数三:修改成了什么值
},
deleteProperty(target,prop){
}
})
技术:一个页面+多个js代码片段
概念:在不刷新整个页面的情况下,进行页面跳转
通过a标签的锚点跳转就可以帮我们实现这个技术
1.a标签在页面跳转时'#' 后面的内容发生了变化
2.拿到'#'后的值:
location.href //需要截取
location.hash //可以直接拿到
3.监听点击不同的锚点
window.onhashchange = function(){}//#后的值发生变化就触发
``
### 12.2 history模式
```js
//H5出现的
history.pushState()//不刷新页面的情况下来操作浏览器的历史记录
//操纵网址#后的内容
语法:history.pushState(state,title,url)
参数一:对象形式记录当前所在的状态//#后内容
参数二:"" //标题,一般空
参数三:跳转到的路径//或跳转的路由
history.state获取页面当前状态//#后的内容
1、解决初始没有内容的问题//判断history为null时,设置默认显示某个页面
2、解决刷新后内容不显示问题//删除可选的参数 url,并设置刷新后页面
3、解决后退时内容不变问题//通过window.onpopstate 监听后退,并设置页面
单例模式:一个类只有一个实例对象
//创建一个变量,判断如果变量为空则new一个实例对象赋给这个变量,否则返回这个变量
类似于观察者模式
一对多的对应关系://例发布者发布消息,所有订阅者都收到消息
1、js是单线程语言。
单线程语言特点:所有的任务按顺序执行。
js是单线程的,无法处理异步任务//它会把异步任务给浏览器,浏览器是多线程的(有一个异步队列)。
js执行代码的顺序:先执行同步任务,执行完毕再去执行异步任务
2、使用回调函数可以取出函数内部异步代码中局部变量的值
1、前后端交互:
前端:html、css、js
后端:java、php、python、node.js
js运行在浏览器上就是js //ECMAScript+DOM+BOM
js运行的node软件上就是后端语言 //ECMAScript
2、什么是服务器:
自己电脑内存是有限的,所以将项目等东西存放在服务器里,需要的时候通过ip地址去访问。用于提供服务。
当电脑开启某些软件时,也可以当做服务器。
3、ip地址:对应了每一个服务器,网页地址栏的信息,IP地址不好记忆,所以转化为域名 https://wwww.baidu.com
4、端口号:ip地址后面的数字,每一个服务器都有很多文件,提供不同服务,有一个端口号
5、接口:
后端提供的,前端连接不同的接口,获取不同的数据,从而实现不同的效果
1、概念:
ajax:在不刷新网页的情况下,向后端发请求,请求少量数据
传统网站:前端发送请求,后端给的是完整的页面,且还会刷新页面
核心对象:XMLHttpRequest
2、语法:let request = new XMLHttpRequest();
属性:
request.readyState:请求状态码
//0(创建了,未初始化) 1(初始化了,准备发) 2(已发送成功) 3(服务器接受并读取) 4(读取请求完成) 可能会出错
request.status 响应状态码 200 (成功的意思) 404 (url错了) 500(服务器出错了)
request.responseText 服务器给我响应回来的数据
方法:
request.open('请求方式','请求服务器的url地址',true(异步)/false(同步));
3、发送请求四步骤:
1)创建XMLHttpRequest对象
2)配置相关信息
3)发送请求
4)接受响应
4、get请求//请求参数?拼接在地址后面
1)var xhr = XMLHttpRequest();
2)xhr.open(get,地址);
3)xhr.send();
4)xhr.onreadystatechange = function(){
if(xhr.readyState == 4 && xhr.status == 200){
console.log(xhr.responseText);
}
}
5、post请求//请求参数写在send里
1)var xhr = XMLHttpRequest();
2)xhr.open(post,地址);
//在发送之前设置请求头
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
3)xhr.send(请求参数);
4)xhr.onreadystatechange = function(){
if(xhr.readyState == 4 && xhr.status == 200){
console.log(xhr.responseText);
}
}
6.xhr的onload事件
xhr.onload() :readyState==4 事件触发
xhr.onload=function(){
if(xhr.status==200){
}
}
7.token:登录接口回复的秘钥
有些接口需要有登录后才可以访问
是否登录成功的标志是:服务器会给一个token字段,下次登陆写上token的值,服务器根据token的值来判断你是否登陆。
1.Promise //ES6新增的解决异步代码的新的方案,是一个构造函数:
//pending 正在进行
//fulfiled 成功的状态 resolve触发
//rejected 失败的状态 reject触发
//可以解决回调地狱
语法:let p = new Promise(function(resolve,reject)){}
//响应成功使用:resolve,响应失败使用:reject
//可以在函数外部取出函数内部异步代码的两种结果
方法:
p.then(function(){},function(){})//二选一,只会走一个
p.catch(function())//只走第二个
p.finally(function(){})//不论成功失败都会走
Promise.all([p1,p2,p3...]) //全部成功会将所有Promise数组返回,只要有一个失败就会返回这个失败的Promise
Promise.race([p1,p2,p3...]) //哪个回来的最快,就是哪个(不论成功与否)
2.使用Promise封装Ajax
3.修饰符 async await//同步写法
//使用async修饰函数,await修饰promise对象
async function fn(){
let res1 = await p1;//等待的结果1,
let res2 = await p2;
}
1、语法:RegExp
1)字面量法:
var reg = /普通字符或规则/修饰符
修饰符:g(全局) i(忽略大小写)
2)构造函数:
var reg = new RegExp('字符串或规则','修饰符')
2、方法:
1)reg.test(字符串) //查看字符串是否满足这个规则(满足true反之false)
2)reg.replace('正则','新字符')
3)//i 无视大小写
4)/sb/g 进行全局查找
5)str.match(reg) //在字符串中查找到符合正则规则的内容,放入一个数组中
6)str.search(reg) 和indexOf作用一样,但search支持正则
3、基本元字符:
\d 一位数字
\D 一位非数字
\w 一位字母下划线数字中的任何一种
\W 表示非单词字符,即不是字母、数字、下划线的字符
\s 一位空白
\S 一位非空格
. 一位任意字符
\. 一位.
例: var reg = /\d/ 是否包含一位数字
4、边界符合:
^ 以...开头
$ 以...结尾
例: var reg = /^abc/ 以abc开始
var reg = /^abc$/ 三位,且只能是abc
5、量词符号:
{m,n} 最少m个,最多n个
例: {m,} 最少m个 {m} 正好m个 /^\d{2,5}/ 只要是2-5个数字
? 0个或1个
+ 一个或者多个
* 0个或多个
6、特殊字符:
[] 一位[]内的任意内容
例: [abc] 一位 a/b/c任意一个 [a-z] 一位 任意一个小写字母
[^abc] //一位,非abc任何一个
() 把括号内当成一个整体
[\u4e00-\u9fa5] 任意汉字
7、例子:
纯数字: /^\d+$/
纯字母: /^[a-zA-Z]$/
纯特殊字符:/^[&$#@;*.!]+$/
1、同源:两个url地址拥有相同的协议、域名、和端口就属于同源
2、http无状态,通过http发送的请求,服务器没有记忆功能,就无法进行一系列的事务操作
3、跨域:不同源的两个url地址相互访问就形成了跨域
4、同源策略:浏览器的一种安全机制,它规定不同源的两个url相互访问会出现"拒绝访问"的错误提示
5、两种解决跨域访问的方法
1)后端处理,后端设置允许任何来源url访问
引入cors()
2)在设置一行请求头 header("Access-Control-Allow-Origin","*")
jsonp 用来解决跨域访问的第二种方案:需要前后端配合来完成
原理:利用一些标签上的属性不受同源策略的限制
发送请求的方案:ajax
script也可以发请求
//使用script发送请求,地址是/wr
<script src="http://localhost:8888/wr"></script>
后端拦截到/wr地址,给你一个响应
语法:
存储/获取:document.cookie = 'key = value'
手动设置过期时间:document.cookie = 'key = value;expires=' + 时间对象//过期时间会自动转为世界标准时间(需要转为东八区时间)
删除cookie:将过期时间设置为负数
特点:
1.只能存字符串,不能存复杂数据类型
2.存储的数据大小有限,只能存4kb左右
3.会话级别的存储,浏览器关闭就没了。但可以设置过期时间
4.cookie的操作必须依赖服务器
//toGMTString() 将时间对象转为东八区时间
cookie和storage两种方式的区别:
1.cookie只能存4kb左右,storage可以存20M左右
2.前后端交互时,cookie的数据会随页面请求自动携带,storage的数据不会自动携带
3.cookie前后端都可操作,storage只能前端js操作
4.cookie默认是会话级,且可以设置过期时间,storage不可以手动设置过期时间
5.cookie有js时就有,storage是h5才出
1、概念:都是通信协议,也就是通信时所遵守的规则,只有双方都按照这个规则"说话",对方才谈理解计算机只所以能全世界互通,协议是功不可没。如果没有协议,计算机各说各话,根本谁都听不懂谁。
2、常见的网络协设:HTTP. TCP. UDP. FTP
3、TCP是协议传输过程:
建立连接:三次握手
断开连接:四次挥手