js学习笔记

JavaScript三大核心:

ECMAScript:JS基础语法
Bom:browser object model 浏览器对象模型
	在bom中给我们提供了一些可以操作浏览器的属性和方法。
Dom:document object model 文档对象模型
	在dom中给我们提供了很多可以操纵文档(页面上的标签)的属性和方法,只要css可以控制的dom都可以操作

一、ECMAScript:

1、书写位置

​ 行内式(内嵌式):写在元素内部,一般不常用。

a:"javascript: alert('11');">超链接
非a:

​ 内部式:可以存在多个,且可以和内嵌式同时存在。

​ 外链式:外链式的script标签中是不可以书写js代码的,写了也会被忽略掉,最常用。

2、注释

​ 单行注释:ctrl + /

​ 多行注释:alt + shift + a

3、量

​ 用来存储和表示数据的容器。

4、变量

​ 用来存储和表示数据的容器,且运行中,变量的值可能会发生变化,必须要定义才能输出。

5、常量

​ 用来存储和表示数据的容器,且运行中,常量的值不会发生变化,不需要定义即可输出。

6、如何定义变量

语法一:(声明并赋值)
	var 变量名 = (数字,字符串(''/""引起来)truefalse)

语法二:(先声明再赋值)
    var 变量名;
    变量名 =语法三:(先声明多个再赋值)
    var 变量名1,变量名2,变量名3;
    变量名1 =1;
    变量名2 =2;
    变量名3 =3
    
报错:Uncaught ReferenceError: a is not defined(变量未定义)

7、变量重新赋值

var a = 20;  创建一个a的变量,并赋值为20
	a = 10;  给a重新赋值
    此时a便是10,20则会被覆盖

8、输出方式

alert(输出内容)//弹出框弹出
console.log(输出内容) //控制台打印
document.write(输出内容) //页面输出,可以识别标签

9、变量的命名

变量的命名规则(必须要遵守,不遵守会报错):
	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

10、js的数据类型

10.1基本数据类型:

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来定义

10.2复杂数据类型:

1.数组:数组里面可以存储很多条数据,数组的单词是array,数组的标志是[](详见P20)
2.对象(P18)
3.时间对象(P24)
4.函数

10.3扩展——数据在内存中的存储方式

js学习笔记_第1张图片

	内存可以分为栈内存、堆内存
	简单数据类型:都是直接存储在栈中
	复杂数据类型:变量在栈中,数据在堆中,会把堆的内存地址赋值给栈中的变量。//所以变量中存的不是数据而是地址
     简单数据类型一个改变不会影响到其他
     复杂数据类型如果公用一个地址,一个改变,会影响到其他

11、检测数据类型

typeof 检测数据类型:
	语法一:typeof	要检测的内容
	语法二:typeof(要检测的内容)
结果:以字符串的形式显示检测的类型
Array.isArray() 检测是否是数组类型//是则true,否则false
A instanceof B 检测a是否是b类型

12、数据类型转换

12.1、数字类型转换

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.转小数,有小数点就可以转换

12.2、字符串类型转换

1.1	语法:String(变量名)
	可以任意类型转换为字符串
1.2	语法:变量名.toString()
	除了undefined、null,可以将任意类型转换为字符串

12.3、布尔类型转换

1.1	语法:Boolean(变量名)
	只有''、0、NaN、null、undefined、false被转换为false,其余都是true

13、运算符

1.算术运算符:+  -  *  /  %(取余)
	+ 拼接:字符串+数字 / 字符串+字符串  
2.关系运算符:>  <  >=  <=  ==  ===  !=
    比较的结果为布尔类型
    =====  ==只比较值(会隐式转换),而===不但比较值,还比较类型
3.赋值运算符:=  +=  -=  *=  /=  %=
	赋值运算符可以让变量的值,发生改变
4.逻辑运算符:||  &&  !
	表达式:能够计算出一个结果的式子:例1+22>3
	条件表达式:能够计算出真或假的表达式  4>2 
	|| 一真及真,都为假为假,短路,前面为假则不看后面
	&& 一假及假,都为真为真,短路,前面为真则不看后面
	! 真为假,假为真
5.自加自减运算符:++   --
	含义:a++++a 自身加1
		 a----a 自身减1
	相同点:都加一或减一
	不同点:在参与输出,运算,赋值等操作时,a++先执行这些操作,再加1
		  					   ++a先加1,再执行这些操作

14、隐式转换

+:数字+字符串   会将数字转换为字符串
- * / % > < == 数字 - 字符串      隐式会将字符串转换为数字

15、判断是否为数字isNaN()

isNaN(内容):等价于isNaN(Number(内容))//会隐式转换
		    检测内容是否为非数字,如何是非数字,结果则为true
		    如果是数字,结果则为false

16、条件分支语句

16.1 条件分支语句

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为常量。

16.2 循环结构:重复做一件事

while 语法:
       	初始化变量;
    while(表达式){	 	
           循环体; 
           变量的更新
    } 
先判断表达式,为true再执行,false则直接结束
do while 语法:
		初始化变量;
	do{	 	
           循环体; 
           变量的更新
    }while(表达式)
先执行一次循环体,再判断表达式,为true再执行,false则直接结束

for 语法:
    for(表达式1;表达式2;表达式3){
       循环体;
    }
        
循环嵌套:
	1.外层循环控制行数
	2.内层循环控制每行执行的个数
	3.外层循环每走1次,内层循环执行一轮
        
break :用于 switch 、循环语句
        用在循环里:终止本层循环。
continue :
        用在循环里:跳过本次循环,继续执行下一次循环

17、函数

17.1 概念:

	函数就是把完成特定功能的一段代码抽取出来,使之成为程序中的一个独立实体,起个名字(函数名)。
	可以在同一个程序或其他程序中多次重复使用(通过函数名调用)

17.2 语法:

定义函数的语法:
	 function 函数名([形参1,形参2...]){,
        函数体
    }
	var 函数名 = function() {
         函数体
    }

调用函数的语法:
	函数名(实参1,实参2);
	调用时:1、实参-传递给形参2、代码从上到下

注意点:
	1. 函数不调用,则不执行
	2. 函数名遵循变量的命名规则和规范
	3. 定义函数的参数叫形参。

return 返回值:
	1.可以带出一个函数的运算结果
	2.终止函数的作用
	3.任何函数都是有return,如果不写,系统会自带一个return undefined

arguments :任何函数都有的一个方法,接收所有的实参

17.3 预解析

1、浏览器在解析代码时,会将 varfunction ,提升到作用域最顶端。
2、然后从上往下依次执行
3、函数提升和变量提升同时存在时,函数提升优先于变量提升

17.4 作用域

1、概念:一段代码生效的范围,分为全局作用域和局部作用域。
全局变量和局部变量的区别:
	全局变量:
    	定义位置:script内部,函数外部。
    	访问的位置:都可以访问
     	生命周期:打开页面产生,页面关闭销毁
	局部变量:
    	定义位置:函数的内部
    	访问的位置:只能在定义的函数内部访问
    	生命周期:函数调用时产生,调用完毕立马销毁
2、访问规则:
	先在自己作用域查找,有就拿来用,没有则向上一级查找,依次类推,如果全局作用域也没有,则报错。
3、赋值规则:
	先在自己作用域内部查找,有就直接赋值
	没有就去上一级作用域内部查找,有就直接赋值,依次类推
	如果一直找到全局作用域都没有,那么就把这个变量定义为全局变量,再给他赋值
4、作用域链:
	各个作用域互相嵌套,链接成的域,叫做作用域链

18、对象

1、对象:编程界万事万物皆对象。
	抽取出的两个概念:特征(属性)、行为(方法)
/*对象的键值对
	键名的命名规则:
		1.符合变量命名规则的都是可以作为键名
		2.可以是纯数字
		3.可以是一些特殊的符号,但是要求用双引号包裹
	键具有唯一性:一个对象中不会出现重复的键
	*/
2、声明方式:
	var 对象名 = {
        属性名 : 属性值
        方法名 : function(){
            方法体
        }
    };
    
3、访问对象的属性或方法:
    	对象名.属性名
	    对象名.方法名()

4、对象的增删改查:
写法1.语法     //.语法的键无法识别变量,会把点后面的当做字符串处理
    增:对象名.属性名 = 属性值
    删:delete 对象名.属性名
    改:对象名.属性名 = 属性值
    查:打印
写法2[]语法    //[]语法会把键当成变量,如果[属性名]属性名添加了引号会识别成字符串
    增:对象名[属性名] = 属性值
    删:delete 对象名[属性名]
    改:对象名[属性名] = 属性值
    查:打印
    
5、对象的遍历
	//第一种:for...in...
     forvar key in obj){
          key//所有键
          obj[key]//所有值
     }

	//第二种:
	Object.keys(obj):以数组形式返回所有键
	Object.values(obj):以数组形式返回所有值

19、简易计算器小demo

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)]

20、数组

20.1 数组的创建

概念:一组数据的有序的集合
方式一:字面量方式
	语法: 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()

20.2 数组的长度

1.获取:
	语法: 数组名.length
2.设置
	语法:	数组名.length = 数字
	将数组长度设置的比初始长度小,会从后往前删除到符合长度为止。
     将数组长度设置的比初始长度大,会用empty占位到符合长度为止。
     将数组长度设置的和初始长度一样,数组无变化。

20.3 数组的索引

1.数组的索引
	数组中数据的编号,叫做索引,或者叫下标
	数组中索引是从左到右,从0开始依次加1
    数组的规律:数组最小索引为0,最大索引为length - 1
2.通过索引获取数组中的数据
	语法:	数组名[索引]
	如果索引存在,则可以得到对应数据
 	如果不存在,则结果为undefined
3.通过索引设置数据
	语法:数组名[索引] = 值
	如果索引存在,则修改对应的数据
    如果不存在,索引大于数组长度,则使用empty占位将,数组长度追加到该索引值,并将该索引值修改为对应数据

20.4 数组的遍历

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
     }

20.5 数组的常用方法

20.5.1 直接修改原始数组

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...)
	返回值:被删除的数据

20.5.2 不改变原始数组

8.	concat()//进行数组的拼接,会把括号内数据和数组拼接为一个数组
	语法:数组名.concat(数据1,数据2...)
	返回值:拼接后的数组
9.	join()//利用连接符将数组中数据连接成一个字符串
	语法:数组名.join("连接符")
	连接符不写,默认连接符为逗号(",")
	返回值:连接符连接后的字符串
10.	slice()//截取指定索引的数组(包前不包后)
	语法:数组名.slice(开始索引,结束索引)
	返回值:截取到的新数组
	注意:只写开始索引,则截取到最后
		开始和结束都不写,则从头到位把数组复制一遍
		写负索引的话则索引从右往左,从-1-2依次递减
11.	indexOf()//从左到右查找该数据
	语法1:数组名.indexOf(数据)//从左到右查找该数据,第一次出现的索引
	语法2:数组名.indexOf(数据,开始索引)//从开始索引位置向右查找该数据,第一次出现的索引(包含开始索引)
	返回值:查找到则返回索引,未找到则返回-1
12.	lastIndexOf()//从右到左查找该数据
	与indexOf()相同,查找方向相反

20.5.3 总结

修改原始数组 不修改原始数组
push() 末尾追加 concat(数据1,数据2) 拼接
pop() 末尾删除 join(“连接符”) 连接符连接成一个字符串
unshift() 开始添加 slice(开始索引,结束索引) 截取(包前不包后)
shift() 开始删除 indexOf(数据,开始索引) 从左到右查找该数据
reverse() 反转 lastIndexOf(数据,开始索引) 从右到左查找该数据
sort() 排序
splice(开始索引,删除个数,插入数据)
指定位置添加或删除数据

20.6 冒泡排序

js学习笔记_第2张图片

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
            }
        }
    }


20.7 选择排序

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
    }

20.8 数组塌陷

1.概念:当从数组中删除某一个数据之后,从删除的数据开始之后的数据的索引都会向前递进。
2.解决方案:在递增之前递减,使索引保持不变
3.数组去重思想1:改变原数组
	先拿一个数据和其他数据比较,如果有相同的则,删掉后面的。
4.数组去重代码1:
方法1var 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--
            }
        }
    }
方法2for (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.数组去重代码2var 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))

20.9 数组常用方法(2)

不改变原始数组

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
    },初始值)
		//初始值加上数组里数据和
	返回值:求和结果

20.9.2总结

item/*每一个数据*/	  index/*索引*/	 origin//原始数组	

不改变原始数组
forEach() 遍历 findIndex() 查找数据索引
map() 加工(映射) every() 判断数据是否满足条件(都要满足&&)
filter() 过滤 some() 判断数据是否满足条件( 一个满足即可|| )
find() 查找数据 reduce() 求和 (prev:初始值)

21、Math常用方法

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的属性  π

21.1 随机数的使用

随机数公式:Math.round(Math.random() * (max-min) + min)   //求min--max的随机数:
//随机索引时  Math.round(Math.random() * (arr.length - 1))     (arr.length-1)是一个整体要括号包起来 

21.2 使用随机数生成一个颜色小demo

   // 方法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

22、字符串

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]
        }

22.1 JSON字符串

JSON字符串:只有属性,没有方法。//遵循外单引号,内双引号(数字可以不使用""包裹)
	JSON字符串==>对象:JSON.parse(str字符串)
	JSON对象==>字符串:JSON.stringify(obj)

22.2 字符串的常用方法(不修改原字符串)

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(次数)
	返回值:重复几次后的字符串

22.3 总结

不改变原字符串
charAt() 查指定索引字符 slice() 截取至结束索引(支持负数) startsWith() 是否以开头
charCodeAt() 查指定索引字符编码 split() 分隔符转数组 endsWith() 是否以结尾
toUpperCase() 字母转大写 concat() 拼接字符串 trim() 去除首位空格
toLowerCase() 字母转小写 indexOf() 左到右查字符,无则-1 trimStart()或trimLeft() 去左侧空格
substr() 截取几个 lastIndexOf() 右到左查字符,无则-1 trimEnd()或trimRight() 去右侧空格
substring() 截取至结束索引(不能负数) includes() 查指定字符,无则false replace() 新换旧

23、字符集(了解)

1.	ASCII:在这个表中有很多字符对应的编码,这个编码是一个数字
   例: 大写A65	小写a:97	空格:32

24、时间对象

24.1 创建:

1000毫秒 = 1秒 
语法1var 变量名 = new Date() //可以得到当前的系统时间。括号里不写内容
语法2var 变量名 = new Date()//括号里写内容,创建指定日期的时间对象
	1)写数字:数字可写多个,通过逗号隔开
	  一个数字代表毫秒数,会从1970-01-01   000秒,再加上时区,加上写的时间
	  一个以上的数字时,则依次为:年 月 日期  时 分 秒  //月份用数字表示时(0表示一月依次递增)  
	2)写字符串
	var 变量名 = new Date('年-月-日 时:分:秒')//字符串方式(1月就是1月)
	var 变量名 = new Date('年/月/日 时:分:秒')

24.2 常用方法

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()

24.3 时间运算

两个时间可以直接相减//的到的值为毫秒数,需要转换
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}`)

25、定时器

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)

二、BOM:

(browser object model )浏览器对象模型

bom的常用方法,统一语法都是window.XXX
但是window可以省略

1、常用方法

1.提示框(弹出框)
	语法:window.alert('提示文本')
	表现形式:一个提示文本+一个确定按钮
	返回值:undefined
2.询问框
	语法:window.confirm('提示文本')
	表现形式:一个提示文本+确定+取消按钮
	返回值:点确定返回true,取消false
3.输入框:
	语法:window.prompt('提示文本')
	表现形式:提示文本+文本输入框+确定+取消
	返回值:点确定返回用户输入的文本,取消null
//注意点:以上三个框有一个共同特点,就是会阻止程序的执行(用户不点击按钮,程序不往下执行)

2、获取浏览器可视窗口的尺寸

概念:可以看见的区域的大小
获取宽度:window.innerWidth
获取高度:window.innerHeight
注意:获取到的值不带单位,获取到的宽高会包括滚动条

3、浏览器的常见事件

1.load事件:加载事件
	语法:window.onload = function() {}
	触发条件:当页面内所有的外部资源(比如html、css、js、图片、视频、音频等)全部加载完毕之后触发
2.resize事件
	语法:window.onresize = function(){}
	触发条件:当页面(窗口)的尺寸发生改变时就触发
3.scroll事件
	语法:window.onscroll = function(){}
	触发条件:只要页面滚动了就会触发
//事件只要触发,就会自动执行function里的代码

4、浏览器的地址栏

1、location对象
	语法:window.location

2、location对象里有一个href属性,可以通过这个属性来获取页面的网址
	获取语法:window.location.href
	设置语法:window.location.href =//重新赋值,改变网址,实现网页跳转的效果(是在当前页面进行跳转的)

3、location对象里有一个方法reload()//刷新网页
	语法:window.location.reload()
	//需要通过绑定别的事件使用,直接写会造成一直刷新的死循环状态

5、浏览器的标签栏

1、打开网页
	语法:window.open('地址')//打开一个网页(是在新窗口打开的)
2、关闭网页
	语法:window.close()//关闭当前页面(模仿关闭按钮)

6、浏览器卷去的尺寸

获取浏览器卷去的尺寸
  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

7、设置浏览器滚动到某位置

语法1:window.scrollTo(x,y)
	x横向位置,y纵向位置,x,y值不用带单位//x和y必须都写,否则会报错
语法2:
	window.scrollTo({left:XXX,top:XXX,behavior:'smooth'})        
	left横向位置,top纵向位置,behavior:'smooth'实现平滑过度效果//可以单独写一个方向,只移横向或纵向

8、浏览器的历史记录

浏览器的历史记录:window.history
再window.history里有三个方法,可以模拟前进、后退、刷新
1、前进://可以去到下一个历史记录
	语法:window.history.forward()
2、后退://可以去到上一个页面
	语法:window.history.back()
3、刷新(前进、回退)//可以模拟前进、回退、刷新
	语法:window.history.go(数字)
	写正数:就是前进,数字是几就前进几步		写负数:就是回退,数字是几就回退几步
	写0:就是刷新

9、总结

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(){}

三、DOM:

(document object model) 文档对象模型

1、获取元素

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()//根据选择器找到符合条件的所有标签
	返回值:伪数组,如何想要操作标签,需要通过索引获取,不能直接操作,找不到则为空数组

2、操作元素

1.获取样式
	获取行内样式:
     	语法:元素.style.样式名
	获取非行内样式:
     	语法:window.getComputedStyle(元素).样式名//window可以不写   	
2.设置样式
	语法:元素.style.样式名 =//只要通过js设置样式,该样式都会设置成行内样式	

3、操作元素的属性

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[属性名]	

4、操作元素的类名

1.方式11)获取类名:
		语法:元素.className()
		//会得到所有的类名,是一个字符串类型,想要得到单个类名,则需要字符串拆分
	2)设置类名:
		语法:元素.className =//注意:会将之前的类名,完全覆盖成设置的名字。需要添加的话需要用+=,做字符串拼接
2.方式21)获取类名:
		语法:元素.classList[索引]
	2)添加类名:
		语法:元素.classList.add(类名)
	3)删除类名:
		语法:元素.classList.remove(类名)
	4)切换类名:
		语法:元素.classList.toggle(类名)//有就删,无就加

5、操作元素的内容

1.获取内容://只可以获取双标签
	语法1:元素.innerText//获取元素下的所有文本
	语法2:元素.innerHTML//获取元素下的所有标签和文本
2.添加内容://只可以给双标签添加内容
	语法1:元素.innerText = 内容//不识别标签
	语法2:元素.innerHTML = 内容//识别标签
	//都会覆盖原先内容 ,想要原先内容保留需要写成+=拼接
3.value//专门用于操作表单元素
	获取:表单元素.value
	操作:表单元素.value = 内容

6、补充

1.this://意思  就是这个
	用的点击事件中,this指你点击的那个元素(点击谁,谁就是this)
2.js中让复选框选中:input.checked = true
   js中让复选框取消选中:input.checked = false

7、总结

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 = 内容
	5this:谁指向它,它就是谁//例:点击的是谁,this就是谁

8、开关思想和排他思想

8.1 开关思想

先定义一个变量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)
    }

8.2 排他思想

先清除所有样式,再给当前元素添加样式

9、获取元素的尺寸

方式1:
     语法:
     	元素.offsetWidth
     	元素.offsetHeight
     	//获取的标准盒宽高尺寸:width+border+padding
     	//获取的怪异盒宽高尺寸:width
方式2:
	语法:
		元素.clientWidth
		元素.clientHeight
		//得到的是该元素:width+padding的尺寸

10、获取元素的偏移值

1. 元素.offsetParent //得到该元素有定位的父级元素(参照物)
2.获取偏移值:
	方式1:
		语法:
			元素.offsetLeft
			元素.offsetTop
			//获取的结果是相对于参照物左边或上边的距离(获取到的结果是不带单位的,是一个数字)
	方式2语法:(了解,几乎不用)
			元素.clientLeft
			元素.clientTop
			//获取的结果是内容和内间距之和与元素边线的距离(得到的就是边框线的粗细)  	

11、获取可视窗口的尺寸

BOM的语法:
	获取宽度:window.innerWidth
	获取高度:window.innerHeight
	//得到的宽高包含滚动条
DOM语法:
	获取宽度:document.documentElement.clientWidth
	获取高度:document.documentElement.clientHeight
	//得到的宽高不包含滚动条

12、瀑布流demo

瀑布流:先渲染一部分数据,然后页面滚动到底部时再加载一部分数据
判断是否滚动到底部:
	公式:可视窗口的高度+页面卷去的高度 > main元素的高度+main元素的偏移量

13、DOM节点

13.1 节点概念及分类

1.概念:把html页面看成一个倒立的树状的结构,一般叫dom树,dom节点就是dom树中的一个元素

js学习笔记_第3张图片

2.Dom节点的分类:
     1)元素节点:就是页面上的每一个标签
     2)文本节点:所有的文本内容,包含换行和空格
     3)属性节点:就是标签上的属性
     4)注释节点:页面上的注释,包含换行和空格

13.2 获取节点

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//返回一个对象(没有属性,则为空对象)

13.3 创建节点

1.创建元素节点
	语法:document.createElement('标签名')
2.创建文本节点
	语法:document.createTextNode('文本内容')
//创造好的东西不会显示在页面上

13.4 添加节点

语法:
	父元素.appendChild(子节点)//将子节点追加到父元素最后
	父元素.insertBefore(子节点,插入到谁的前面)//添加节点至谁前面

13.5 删除节点

语法:
	父节点.removeChild(子节点)//把子节点从父节点下删除
	节点.remove()//删除自己

13.6 替换节点

语法:
	父节点.replaceChild(新节点,老节点)

13.7 克隆节点

语法:
	节点.cloneNode(参数)//把节点复制一份
		参数写true则,复制自己和后代
		参数写false为只复制自己(默认值)

13.8 节点属性

	1)nodeType:节点属性,可以通过数字判断你的节点类型//返回值:一个数字
		元素节点:1
		属性节点:2
		文本节点:3
		注释节点:8
	2)nodeName:节点名称
		元素节点:大写的标签名称
		属性节点:属性名字
		文本节点:#text
		注释节点:#comment
	3)nodeValue:节点内容
		元素节点:null
		属性节点:属性值
		文本节点:文本内容(包含换行和空格)
		注释节点:注释内容(包含换行和空格)


14、代码的执行过程

同步代码:从上到下依次执行
异步代码:定时器、事件
代码执行过程://先执行同步代码,最后执行异步代码

15、事件

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事件类型',要绑定的事件处理函数)

16、事件类型

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属性,值为true1)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,窗口关闭的时候就触发(可以存个数据)
     案例:关闭之前存一次时间,打开再获取一次,可以弹框一个:距离上次见面?时间。

16.1 总结

鼠标事件
click //左键单击 dblclick //双击 contextmenu //右键单击
mousedown //按下 mouseup //抬起 mousemove //移动
mouseover //移入(子元素触发) mouseout //移出(子元素触发) mouseenter //移入(子元素不触发)
mouseleave //移出(子元素不触发)
键盘事件
keydown //键盘按下 keyup //键盘抬起 keypress //键盘键入
表单事件
focus //得到焦点 blur //失去焦点 change //内容改变
input //输入 submit //提交 reset //重置

17、本地存储

方式一: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才出

18、事件对象

1.概念:事件发生时,会产生一个东西叫:事件对象//会存储本次事件发生时产生的一些信息
2.获取事件对象:
	在事件处理函数里写一个形参,该形参由浏览器自动赋值
	事件源.onclick = function(e){//e就是事件对象
		var e = e || window.event//IE兼容写法
	}

18.1 鼠标

1.获取事件对象中和鼠标相关的信息:
	方式一:client:得到光标相对于'浏览器可视窗口'的左上角的坐标值
		语法:事件对象.clientX   事件对象.clientY
	方式二:page:得到光标相对于'文档流'左上角的坐标值
		语法:事件对象.pageX   事件对象.pageY
	方式三:offset:光标相对于'准确触发事件的元素'左上角的坐标值
		语法:事件对象.offsetX   事件对象.offsetY

2.鼠标跟随案例
	在css里写:pointer-events:none//阻止事件传入,谁抖给谁加

18.2 键盘

	1)keyCode //可以得到你按下了哪个键(onkeydown 按下)
	2)shiftKey //按下了shift键时返回true
	3)ctrlKey  //按下了ctrl键时返回true
	4)altKey   //按下alt键时返回true
	5)metaKey(指的是window键) //按下win键时返回true

18.3 事件传播

1.w3c规定事件如何传播:
2.阻止事件冒泡:e.stopPropagation

18.4 事件默认行为

1.阻止事件的默认行为
	e.preventDefault() //
	return false //只能0级使用

18.5 事件委托

	利用冒泡的原理,将原本绑定在子元素的事件委托给父元素,可以使用e.target获取你具体点击的元素

18.6 e.target和this的区别

this 是绑定事件的事件源
e.target 是触发事件的事件源

19、 ES5新增语法

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指向改变后的函数

19.1 this指向问题

1.事件处理函数:里面的this都指向,事件源
2.定时器函数:this指向了window
3.对象里的方法:this指向对象本身
4.普通函数:this指向window
5.箭头函数:this指向了上一级

20、 ES6新增语法

1.新增的定义变量:let letvar的区别:	      
	let	1.不可以在同一个作用域内定义相同的变量
		2.不可以挂载在window
		3.会形成作用域
		4.会形成暂时性死区(先定义后使用)
		5.不会预解析
	var	1.可以在同一个作用域内定义相同的变量
		2.可以挂载在window
		3.不会形成作用域
		4.会形成暂时性死区(后定义可以先使用)
		5.会预解析
2.定义常量:constlet
	相同点:
		1.不可以在同一个作用域内定义相同的变量
		2.不可以挂载的window
		3.会形成作用域
		4.会形成暂时性死区(先定义后使用)
		5.不会预解析
	不同点:
		1.const值不可以被修改,let可以
		2.const必须声明即赋值,let不需要
3.模板字符串:``反引号 //支持换行,能够识别使用${}包裹的变量

20.1 箭头函数

概念:匿名函数的简化
语法: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

20.2 解析赋值

1.数组的解析赋值:
	语法:var [a,b,c,d] = [12,43,543,432];//a,b,c,d对应数组中的数据
2.对象的解析赋值:
	语法1var {name,age} = {name:'zs',age:18};
	语法2var {name:x} = {name:'zs',age:18};//只取出name,并起别名为x

20.3 扩展运算符

作用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};

20.4 默认参数

概念:当不传参数时,使用的是默认参数
	function(a=1){}  
	
arguments //任何函数都有一个arguments,保存着所有的实参,伪数组(不常用)

20.5 其他

1.模板字符串`${包裹变量}`
2.for...of 遍历数组的元素
3.class类//详见面向对象

20.6 map和set集合

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遍历的是键值对

20.7 ES6的模块化开发

1.一个功能一个js文件
2.模块化的好处:复用性提高,易维护,减少了命名冲突
3.导入语法:
<script src=""></script>//会发生命名冲突

	//导入的是对象形式,同名也不会发生命名冲突
	<script type="module">
      	import 模块名(自定义名) from './cart.js'    
      </script>
4.导出语法://导出的是对象形式
	export default {
          导出的内容
          a:a,
          fn:fn
     }
5.注意点:
	打开的时需要从服务器打开

21、 运动

1.给元素添加定位,通过改变元素的定位,完成元素的移动

四、面向对象编程

1.面向过程编程:想要实现一个功能,找到实现的思路,分析完成该功能的步骤,按照步骤一步步来完成。
2.面向对象编程:想要实现一个功能,找到一个能帮助我们完成这个功能对象,让这个对象调用对象中的具体方法来进行的实现的。
3.面向对象的核心:封装、继承

1、对象的四种创建方式

1.var obj = {};//字面量法
2.var obj = new Object();//内置构造函数来创建
3.封装函数,批量创造对象//工厂模式创建对象
4.通过构造函数模拟类,通过这个类创建对象//ES3提出的,没有类的概念。
	例:function 构造函数名(){
          
     }
	构造函数与普通函数的区别:
          构造函数: 1.首字母大写,且要求是名词 
          	      2.调用:通过new来调用 
                     3.this指向new出的对象本身 
                     4.第一行有一个默认的thisthis默认值为{},最后一行有个默认的return this 
                     5.为了实例化出一个对象,通过这个对象来调用属性和方法来完成具体的功能。
          普通函数: 1.驼峰命名,要求动词 
          	     2.直接调用 
          	     3.this指向window 
          	     4.默认return的是undefined 
          	     5.为了实现一个功能。
	constructor属性:
5.class 类

2、构造函数原型

1.用于解决构造函数每个实例调用方法时,需要单独开辟新地内存空间存储,造成的内存占用过大的问题。
2.解决思路:找一个对象,将这个方法放到这个对象上,只要实例化的对象可以访问到这个方法即可。
3.原型对象://任何构造函数都有一个原型对象(prototype属性),实例化的对象可以直接访问
	获取:构造函数.prototype
	使用:将方法放在原型对象上,这样每一个实例对象都可以访问这个原型对象,不需要重新开辟内存。
//prototype属性正好可以解决函数重复占用内外的问题

3、对象原型

1.构造函数被实例化后都会有一个__proto__属性,指向了构造函数的prototype原型对象,所以对象才可以使用构造函数prototype原型对象的属性和方法。

3.1 constructor构造函数

对象的原型__proto__和构造函数prototype原型对象里都有一个constructor属性,constructor称为构造函数,指回了构造函数本身。

4、原型链

js学习笔记_第4张图片

每一个对象都有一个__proto__属性,它指向了创建它的,构造函数的原型对象,原型对象也是一个对象,它也存在__proto__属性,这样一层层向上指向的规则形成了原型链。
在没有继承的情况下实例对象的原型对象指向的是Object的原型对象

5、class类

1、 创建类 
class 类名{
     constructor(参数列表){
 
     }
     //方法写在这里,相当于放在了prototype原型上
}
2.注意点:
	1new 时会调用constructor构造函数
	2)constructor构造函数的this指向是实例化出来的对象
	3)在constructor平级的位置可以书写一个方法,这个方法就放在了该类的原型对象上
	4)原型对象的方法里的this也指向实例化出来的对象
	5)原型对象的方法可以直接访问构造函数的属性
	6)构造函数中可以直接访问原型对象中的方法
	

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('吃饱就睡');
    }
4ES6继承:通过extendssuper关键字
	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);
        }
    }

7、闭包(closure)

特点: 1.函数嵌套函数
	 2.内部函数持有外部函数的局部变量
	 3.内部函数就是闭包
如何查看是否形成闭包:控制台打断点查看//closure
作用: 1.延长局部变量的生命周期
	 2.让局部变量持久保存在内存中
	 3.私有化变量的同时,防止全局变量污染
缺点: 1.内存泄漏、内存占用过大

8、函数柯里化

函数柯里化的形式:把接受多个参数的函数,变成接受单一参数的函数,而且返回结果是新函数的技术,让新函数处理剩余参数。
	好处:减少冗余,将代码变得简洁,参数可以实现复用。
	//把形式一转化为形式二的过程叫做函数柯里化
	//形式一
	function getSum(a,b,c){
		return function (){
			return a + b + c;
		} 
	}
	//形式二
	function getSum(a){
		return function(b){
			return function(c){
				return a + b + c;
			}
		}
	}

9、递归

js学习笔记_第5张图片

1.概念:在函数内部直接或间接的调用函数本身;
2.注意点:递归要有出口,没有出口就形成死递归
例:求n的阶乘
function jieC(n){
     if(n==1){
          return 1;
     }else{
          return n * jieC(n-1);
     }
}
3.调用:
	调用阶段:从外到里一层一层开辟新的空间
	返回阶段:从里到外一层一层返回值

10、深浅拷贝(针对于引用数据类型)

1.浅拷贝:复制了一份,相互之间会有影响
	数组:
          1.直接赋值
          //下面只能实现单层深拷贝,对于多层是浅拷贝
          2slice(0)
          3)  concat()
          4)  ...扩展运算符
          5)  for遍历
          ...
	对象:
		1)直接赋值
		//下面只能实现单层深拷贝,对于多层是浅拷贝
		2) ...扩展运算符
		3) for遍历
2.深拷贝:复制了一份,相互之间不会有影响
	通过JSON.parse(JSON.stringify(obj))实现深拷贝。
	for 循环加递归

11、Object.defineProperty():为对象增加属性(ES5新增)

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
	}
数据劫持:

11.1、数据代理

数据代理:通过一个对象代理对另一个对象的操作(增、删、获取、设置)
vue2.0 使用Object.defineProperty()  有点问题 只有获取和设置
vue3.0 使用proxy         有获取、设置、增、删
//不直接对源对象进行操作,而是通过操纵代理对象,进行对原对象的增删改查
new Proxy(obj,{
     get(target,prop){//参数一:代理的对象,参数二:访问的哪个属性
      },
     set(target,prop,val){//参数三:修改成了什么值     
     },
     deleteProperty(target,prop){
     }
})

12、单页面技术(SPA)

技术:一个页面+多个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 监听后退,并设置页面

13、设计模式

13.1 单例模式

单例模式:一个类只有一个实例对象
//创建一个变量,判断如果变量为空则new一个实例对象赋给这个变量,否则返回这个变量

13.2 发布订阅模式

类似于观察者模式
	一对多的对应关系://例发布者发布消息,所有订阅者都收到消息

14、同步异步

js学习笔记_第6张图片
js学习笔记_第7张图片

1、js是单线程语言。
	单线程语言特点:所有的任务按顺序执行。
	js是单线程的,无法处理异步任务//它会把异步任务给浏览器,浏览器是多线程的(有一个异步队列)。
	js执行代码的顺序:先执行同步任务,执行完毕再去执行异步任务
2、使用回调函数可以取出函数内部异步代码中局部变量的值

15、Ajax

js学习笔记_第8张图片

15.1 认识前后端交互

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、接口:
	后端提供的,前端连接不同的接口,获取不同的数据,从而实现不同的效果

15.2 认识Ajax(Asynchronous Javascript And XML)

js学习笔记_第9张图片

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)接受响应
4get请求//请求参数?拼接在地址后面
	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的值来判断你是否登陆。

15.3、补充

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;
}

16、正则表达式

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]$/
	纯特殊字符:/^[&$#@;*.!]+$/

17、认识同源和跨域

1、同源:两个url地址拥有相同的协议、域名、和端口就属于同源
2、http无状态,通过http发送的请求,服务器没有记忆功能,就无法进行一系列的事务操作
3、跨域:不同源的两个url地址相互访问就形成了跨域
4、同源策略:浏览器的一种安全机制,它规定不同源的两个url相互访问会出现"拒绝访问"的错误提示
5、两种解决跨域访问的方法
	1)后端处理,后端设置允许任何来源url访问
     	引入cors()
	2)在设置一行请求头 header("Access-Control-Allow-Origin","*")

17.1、jsonp解决跨域问题

jsonp 用来解决跨域访问的第二种方案:需要前后端配合来完成
原理:利用一些标签上的属性不受同源策略的限制
发送请求的方案:ajax
		   script也可以发请求
		   //使用script发送请求,地址是/wr
		   <script src="http://localhost:8888/wr"></script>
		   后端拦截到/wr地址,给你一个响应

18、本地存储cookie

语法:
	存储/获取: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才出

19、什么是通信协议

1、概念:都是通信协议,也就是通信时所遵守的规则,只有双方都按照这个规则"说话",对方才谈理解计算机只所以能全世界互通,协议是功不可没。如果没有协议,计算机各说各话,根本谁都听不懂谁。
2、常见的网络协设:HTTP. TCP. UDP. FTP
3TCP是协议传输过程:
	建立连接:三次握手
	断开连接:四次挥手

你可能感兴趣的:(javascript,学习,前端,html,开发语言)