笔记批注
< !—橙色 ctrl+alt+o 重述存在问题 -------->
< !----红色 ctrl+alt+r 如面试题 ---->
< !—浅蓝 ctrl+alt+b —>知识点
辅助习题收集:js案例.md
skills
-
控制台语言:
-
软件
-
md文档
- vscode浏览
- 直接安装
-
查找代码问题:
- 代码结合二分法,逐行注释查找;
-
插件:
- 驼峰单词翻译 驼峰翻译助手
- liveserver 插件
-
百度脑图官网
- https://naotu.baidu.com/home
序言
- 前端三件套
- html结构层 --骨架
- css样式层
- js行为层
js
-
ECMAScript
-
js的语法标准
-
相关公司协会
- ie ==>jScript
- 网景==》javaScript
- ECMA 欧洲计算机协会
- 浏览器中脚本进行标准化–一本书-约定约定
- 规定了js 中所有内容 color 属性表示 字体颜色
- ecmaScript 是一个 文字的性约定、–前几周要学的就是es语法
-
-
BOM
- 浏览器对象模型–操作浏览器
-
DOM(用的比较多)
- 文档(htmo页面)对象模型(对文档进行操作-增删改查)
- 通过js语法–来控制浏览器
js位置
内嵌式js
- 位置:任何位置都可;
- 通常在body标签的结束标签之上;
外链式js
- 引入:
- < script src=“…/引入内容”> ----js的引入
- 省略 type=“text/javascript”
- link href=“…/” ----css的引入
- < script src=“…/引入内容”> ----js的引入
行内式js
<div style='color:red' onlick="console.log(hello world)>按钮</div>
- 引号:外双内单谨慎选择;
符号
-
注释:
-
语法
- 单行注释; ctrl+/
- 多行注释; alt+shift+a
-
作用
- 解释说明
- 查找问题,调试程序
-
方法:
- 调试:二分法调试
-
-
引号
- 单引号’’
- 双引号“”
- 反引号 `` 可以换行
-
展开语法
- …
变量
-
定义:数据的储存容器,存储数据中的标识符,给某一个内存起了一个名
-
语法
//变量的语法: var 变量名(); var age=10;//定义一个变量并且赋值为10; //多个变量的定义 var a,b,c,d
-
命名规则:
- 只能:数字,字母,下划线,美元符号组成
- 开头:不能由数字开头
-
命名规范:
- 变量语义化,适合单词
- 小驼峰,第二个单词起首字母大写;工具:驼峰翻译助手
-
关键字
- js中有的特殊关键词
-
保留字
- 未来可成为关键字
- 特殊的name;不能乱用
数据类型01(简单,复杂)
- 简单数据类型
- 数值number,字符string,布尔Boolean,空null,Symbol,bigintes6新增
- 复杂数据类型
- 对象,(Array,object)
/*数值型
浮点数19.1,整数19
二进制
0b开头 var n1=0b10 打印出来是10进制的结果
八进制
0开头
十六进制
0x开头 var n=0xa
*/
- 验证:
- NaN 非数字类型
- typeof 检查变量类型结果
- number ,string, object,Boolean
报错
- SyntaxError 语法错误–有行数的提示;
复习
-
导图
http://naotu.baidu.com/file/744f2afca22cdaa55c5a8d83db2ddad5?token=dee687b62dfcd7dd
数据类型02(布尔,null,undefined)
-
布尔
- true/false;
- 判断:r1 = typeOf isWin
- 输出:console.log(r1);
-
null
- type of null//object;
-
undefined
- js语言特有;
- 声明但没有赋值,undefined;灰色;
- 没有声明没有赋值,undefined
- js语言特有;
-
对象
var obj={ name:"zhou", //name:属性名,key /zhou:属性值;键值 sex:"girl", isReg:false friend:functi{ namme:'xiao', age:12 } }
- 打印
//法一: console.log(obj.name); //法二: console.log(obj[age]); console.log(obj); //打印没有定义的属性值 undefined;
数据类型的转化
- 前情提要:页面中的所有内容都是字符串,需要转化为数值;
String转Number
-
Number()
- 有字符串的返回,保留小数;
- 互相转化为布尔值
- 无法转换的返回NaN,如数字当中有字符串;
-
parseInt() 解析变量中的整数部分;
- 提取整数部分,小数转为整数 //12.2323==>12
- 字符第一就是字符. //NaN
-
paresefloat();
var str='asd'; //1. Number() var num=Number(str); //2. parseInt() var //3. pareseFloat(); 123.1 123.1a as123.1
-
强制转化;(隐式转换)
-
除加法外的数学运算;
-
条件:运算符两边都是数字可运算的,否则返回’NaN’
-
关于加法
//加法是连接符; console.1og(1 + 1);//2 console.log(1 + '2');//'12' console.1og( '2323' + '2' );//'23232'
-
Number转字符串
-
String
-
toString
-
加法连接符
var num=10; var r1=String(num); var r2=r1.toString; var r3=r1+''; 隐式的转化,将数字与空字符拼接; //注意:空字符串不同于空格
转布尔值
-
’ ’ 0 null undefined NaN ==>可以转为false ;其他数据都能转化为false;
-
其余都是true ,比如负数,空格;
console.log(Boolean(0));//false console.log(Boolean(undefined));//false console.log(Boolean(' '));//true
运算符
-
算数运算符
+ - * / % (求余,判断奇偶性 / 能否被几整除) ^ (求次方)
-
等值运算
1=='1' == //全等 ,比较两者的值,如果是数字型字符串,会转换 true === //全等,比较值以及类型,不会转换 false
-
比较运算
返回值:true/false; >= <= != a=1; b=2; var r1 = a > b //false只是在计算中充当0 但返回值不代表等于0
-
逻辑运算符(返回true)
&& 并且 and || 或者 or ! 非
//短路运算 console.log(11 || 12);//11 //或运算,如果能执行则短路,后面就不会继续运算 //且运算 console.log( 11 && 12)//12 console.log(undefined || 12 )//12
-
自增运算
1. += 2. -= 3. *= 4. /= 5. %= num=num%2; 6. a++ ++a 先用后加 先加后用 - var a=0 ; - a++; console.log(a) //a=0; - ++a; console.log(a) //a=1; //写代码不关心,面试关心
-
小括号
强化练习–运算符
// 小明要到美国旅游,可是那里的温度是以华氏度为单位记录的。
// 它需要一个程序将华氏温度(80度)转换为摄氏度,并以华氏度和摄氏度为单位分别显示该温度。
// 提示:摄氏度与华氏度的转换公式为:摄氏度 = 5/9.0*(华氏度-32)
弹出输入框:prompt(‘’)
- 确定:保存字符串
- 取消:保存一个空 null 注意此处的null为object
- 弹框会阻止代码的执行
复习
http://naotu.baidu.com/file/744f2afca22cdaa55c5a8d83db2ddad5?token=dee687b62dfcd7dd
- 布尔值;
- null;
- 简单数据类型;
- 类型转换;
- 转数字
- Number
- parseInt
- parseFloat
-
- 转字符串
- String
- toString()
- +‘’
- 转布尔
- Boolean ‘’ undefined NaN 0 =>false
- 转数字
- 算数运算符
- +,-,*,/,%,**
- 比较运算符
程序结构
顺序结构
- 代码自上而下
选择结构
-
判断分支结构
if(条件){ }else if{ } //三元 条件判断? true: false
-
if
-
if else
-
if else if else 保证顺序;
-
if else 的语句如果仅有一句,可以省略大括号;
-
简写:三目运算符;
- 单目(一元):
- 定义:运算符号两边仅有一边有代码
- 例子:!true; i++
- 双目(二元):
- 定义:运算符两边都可以由代码
- 例子:> < = !
- 三目:
- 语法:? :
- 若成立,执行:前方的运算。
- 单目(一元):
-
switch;
-
场景:固定值;选择情况少时,效率优于 if
-
穿透:break 的合理省略
switch(key){ case value:; break; default; }
穿透的习题–switch穿透
// 5. 输入月份,显示当月的天数 + 判断几月 +判断年份是否闰年; // 6. 根据输入的三个数字,判断是这一年的第几天
- 穿透倒着书写的应用;
-
循环结构01
-
while
while(true/false){ console.log() 限制条件; }
-
do while
do{ 循环体; } while()
-
for
for( var i=1,j=2;i<=条件;i++){ } 1. 单循环; 2. 双循环;
for 循环的括号内可以声明不止一个变量;
-
for循环的习题:–for循环
1. 求100以内所有偶数的和 2. 求出1/1-1/2+1/3-1/4…..1/100的和 var i=1; (倒数和) 3. 打印出1000-2000年中所有的闰年,并以每行四个数的形式输出 4. 使用 `*` 打印三角形 5. 输出100-200之间所有的质数 6. 求1+2!+3!+...+20!的值(阶乘和) 7. 有一个棋盘,有64个方格,在第一个方格里面放1粒芝麻重量是0.00001kg,第二个里面放2粒,第三个里面放4,第四个8 ,棋盘上放的所有芝麻的重量(后一个是前一个两倍) 8. 打印九九乘法表 9. 完成一个梯形/三角形打印功能 10. 篮球从5米高的地方掉下来,每次弹起的高度是原来的30%,经过几次弹起,篮球的高度小于0.1米 11. 100的阶乘; 12. 水仙花数; 13. 质数;
0做分母正无穷,(计算机当中)
结束循环
- break;中断整个循环
- continue; 提前结束某一次循环;
- 判断结构算循环吗,能否中断
浮点数精确
0.1+0.2=0.300000000000004
-
成因:电脑只能存储整数
-
科普:0.300000000000004.com
-
解决办法:
var num = 0.1 + 0.2; var res = num.toFixed(3); console.log(res); console.log(Number(res));
debug工具
-
定义:bug 程序漏洞;debug 解决bug
-
方案:
-
log 打印
-
状况:效果有问题-- 变量的值 跟我们预期的不一样
-
状况2:或者是 条件不执行,循环执行有问题
-
log变量的值, 打印条件
-
-
断点 逐步观察程序的执行
-
终端程序执行的一个点
-
chrome 开发者工具-里面的源代码-source
-
单步调试 next按钮
-
resume 按钮–两个断点之间的调试
-
-
函数:
-
分类
-
声明函数:
- 命名
-
赋值函数(函数表达式)
- 匿名
-
箭头函数(es6)
- 匿名
- 作用:省略function关键字,以及根据需求选择(){}
//1. function fn(){ } fn(); //2. var fn=function (){ } fn(); //3. //3.1 多行 (c1,c2,...c3)=>{ 多行代码 } //3.2 单行 (c1,c2,..)=> 单行代码 //3.3 无参数 ()=>{} //3.4 单个参数 =>{}
-
-
组成
-
形参,实参(传入)
-
例子:
1. 形参>实参 - 多余的形参undefined 2. 形参<实参 - 多余的实参 没用
function fn(num1, num2) { // 函数内部可以使用 num1 和 num2 } // 本次调用的时候,传递了两个实参,100 200 和 300 // 100 200 对应了 num1 num2,300 没有对应 // 函数内部没法依靠变量使用 300 fn(100, 200, 300) function fn(num1, num2, num3) { // 函数内部可以使用 num1 num2 和 num3 } // 本次调用的时候,传递了两个实参,100 和 200 // 对应了 num1 和 num2 // 而 num3 没有实参和其对应,那么 num3 的值就是 undefined fn(100, 200)
-
-
调用
-
区别
- 声明式调用与声明的前后无需固定;
- 赋值式,调用必须在声明后。
fun()
-
-
特殊值
-
伪数组arguments 只存在于函数重
arguments[0]
-
函数内部的是局部变量,外部无法使用;
-
return
-
-
优点
- 复用性
- 简洁
-
函数的习题–函数
1. 求和差 2. 比较大中小 3. 编写任意个数字的求和函数 sum(1,2,3,4,5,6) 4. 编写生成4位数字验证码的函数 5. 编写一个函数,计算任意两个数字之间所能组成的奇数个数,数字必须是个位数 6. 某个公司采用公用电话传递数据,数据是四位的整数,在传递过程中是加密的
预解析
-
预解析与执行上下文相同与声明提升
-
定义:在执行代码之前,对代码首先编译
-
场景:js为解释代码,运行过程中,两个环节;
- 解释代码
- 执行代码
-
-
分类:
-
声明提升
- 变量提升: 声明提升,赋值不提升,不报错
- 变量提升的变量运算 结果为NaN
- 函数提升:
- 声明式函数;
- 声明式函数赋值;
- 赋值函数;
- 变量提升: 声明提升,赋值不提升,不报错
-
-
特点:
-
整体提升至script 最前面;
-
定义之前使用该变量,不报错,但显示undefined;
-
函数表达式的名称只能在函数内部使用,不可使用在外部;
ps: 声明提升现象,不要使用,新版本es6会报错,由于let const的特性吗?
1. var bar; var foo = function bar(){ console.log(1); }; bar();//TypeError: bar is not a function
-
-
样例:
-
深入理解javascript作用域系列第三篇——声明提升(hoisting) - 小火柴的蓝色理想 - 博客园 (cnblogs.com)
//1. console.log(i);// 声明提升,输出undfined var i = 1; //1.1提升后 var i; console.log(i); // undefined i = 1; // 初始化不提升 //2 函数声明类型; f(); function f(){ console.log("test"); } //2.1提升后 function f(){ console.log("test"); } f(); //3函数表达式型: foo(); var foo = function(){ console.log(1);//TypeError: foo is not a function } //3.1提升后: //变量提升后,代码如下所示: var foo; foo(); foo = function(){ console.log(1); } //3.2 foo();//TypeError: foo is not a function var foo = function bar(){ console.log(1); }; //3.3 具名的函数表达式提升后: var foo; foo();//TypeError: foo is not a function foo = function bar(){ console.log(1); };
PS:即使有具名的函数表达式也无法被提升;
-
作用域scope
- 全局作用域
- 内部的变量称为全局变量;
- 局部作用域(函数内部)
- 按照层次向上找,先提升,再越层级查找;
- 易错:提升后但是没有赋值的情况,也不用翻阅层级查找了;
- 案例–预解析+作用域
递归
-
自己调用自己(已知数学中的递推==》转递归);容易爆栈(传入数值较大时,易爆栈)
//报错:死递归,溢出最大调用栈/爆栈; box(){ log('box1'); box() log('box2');//不会执行,循环调用上方; } //有意义的递归:添加限制条件; a(n) =a(n-1) + n //先递执行到一半挺住再下一级,依次换级,最终查找到界线如n=1时 //再归逐级向上;
-
尽量使用循环,递归占用内存,时间复杂度,空间复杂度太大,效率低;
-
使用场景:
- 数学有递推式/递推过程 的问题
-
案例–递归
1. 阶乘 2. 斐波那契数列 F(n)=F(n-1)+F(n-2) 3. 最大公约数
对象
-
定义:键值对的合集
-
对象中的函数不叫属性称为方法
-
创建方式:
- 字面量创建
- 构造函数 new
-
函数的增删改
// 1-字面量创建 var obj = { // 属性 name: '晓红', age: 18, // 方法名:函数 // run方法 run: function (num) { console.log('跑' + num + '米'); } } console.log(obj.name); console.log(obj['name']); obj.run(10) obj.run(100) // 2-构造函数创建 var obj2 = new Object(); var obj3 = {};//字面量就是构造函数创建的简写 console.log(obj2); console.log(obj3); // 3-操作 // 添加一个属性 obj2.name = '小张'; obj2.age = 18; // 修改属性 obj2.name = '张先生'; // 获取属性 console.log(obj2.name); // 删除属性 delete obj2.name; console.log(obj2);//{age: 18} // 添加一个方法 obj2.run = function () { console.log('跑'); } // 覆盖原来的方法 obj2.run = function () { console.log('新的跑'); } // 调用方法 obj2.run() // 删除方法 delete obj2.run;
数组
-
类型:是一个对象,可存储有序的数据结构;
-
创建:
1. 字面量 [数据1,数据2] [元素1,元素2] 多个元素都逗号隔开 2. 构造函数 参数只有只一个的时候,并且是 参数表示 数组的元素个数, 其他情况下,参数都表示 数组的 - 推荐使用 字面量创建
-
数组–有属性
-
下标/索引 获取元素
- arr[0] 获取下标为0位置的元素
-
修改对应位置的:arr[0] = 100;
-
length-长度属性
-
数组元素个数
-
循环遍历数组中的元素
-
// 1-字面量 var nameArr = ['zhansan', 'lisi', 'wangwu']; var ageArr = [1, 23, 3, 4, 5, 6,]; var flagArr = [true, false, true]; var stuArr = [{ name: '周蓉' }, { name: '曾夏颖' }]; var testArr = [1, 'zhangsan']; console.log(typeof nameArr);//object console.log(nameArr); // 2-构造函数 var arr1 = new Array();//===> var arr1 = [] console.log(arr1); // 3-参数元素 var arr2 = new Array(1, 2, 3); console.log(arr2); // 4-参数表示数组的长度 var arr3 = new Array(100) console.log(arr3); // 数组的属性 var arr4 = [9, 8, 7]; console.log(arr4); // 根据下标获取对应位置的元素 console.log(arr4[0]); console.log(arr4[1]); console.log(arr4[2]); // 根据下修改对应位置的元素 arr4[0] = 900; console.log(arr4); // 长度属性 console.log(arr4.length); // 长度可以修改,但是很少这样修改 // arr4.length = 1 console.log(arr4); // 0 1 2 // 循环遍历数组的元素 // 数组所有元素的和 var sum = 0;//记录所有元素的和 // var res = '';//将数组中所有的元素拼接成一个字符串 for (var i = 0; i < arr4.length; i++) { //i 0 1 2 --数组的所有元素的下标 //获取对应下标的元素 var item = arr4[i]; console.log(item, i); // 循环中把 所有的元素 都累加到 sum上 sum = sum + item; res = res + item; } console.log(sum);//915 console.log(res);//'90087'
-
数组增删方法:
- 学习重点:
- 记忆:功能,名字,参数
- [] 表示可省略;
//1. push()
方法名:
功能:尾部添加 ! 会修改原始数组
参数:添加元素
返回值:添加后的数组长度 ! 返回的长度
//2. pop()
方法名:
功能:尾部删除 ! 会修改原始数组
参数:删除元素
返回值:删除后的数组长度 ! 返回的长度
//3. unshift()
方法名:
功能:头部添加 ! 会修改原始数组
参数:添加元素
返回值:添加后的数组长度 ! 返回的长度
//4. shift()
方法名:
功能:头部删除 ! 会修改原始数组
参数:删除元素
返回值:删除后的数组长度 ! 返回的长度
截取/插入方法:
//1. splice(开始值,删除元素,[插入元素]) 用的最多
参数:(开始index,删除个数)
arr.splice(0,1)
功能1:截取数组并删除 !会修改原视数组
返回值:被删除的元素组成的数组
arr.splice(1,0,'插入元素')
功能2:插入元素任意位置前(替换)
数组排序方法:
//1. reverse()
参数:无
arr.reverse()
功能:数组返回 !不会修改修改原数组
返回数组
//1. sort()
参数1:不填入
arr1.sort()
功能1:冒泡排序按照字典大小排序(升序) !不会修改修改原数组
返回值:返回后的数组
[1,2,3,11,22].sort()//[1,11,2,22,3]
['bb','abc','bc'].sort()//['abc','bb','bc']字母越大越靠后,先比第1位再2位3位;
//1.1 sort(function(a,b){})
arr2.sort(function(a,b){})
参数2:填入函数
功能2:冒泡排序按照大小排序
arr.sort(function (a,b){
//a,b 是数组的元素
return b-a;//[13,11,3,2] 降序;b-a>0
return a-b;//[2,3,11,13] 升序;a-b<0
})
//1.2 sort(function(a,b){})
参数3:填入函数
功能3:乱序排序;
arr2.sort(function(a,b){
//实现思路: 随机函数使其>0 <0 不确定;
return Math.random()-0.5 几率各一半
})
//1.3
参数4:填入对象
功能4:按照对象某一个属性值对对象进行排序;
arr4.sort(function(a,b){
return b.age -a.age;
})
数组合并方法:
//1. concat()
arr.concat()
参数:(元素/数组)
功能:将arr与传入的数组合并成一个新的数;
返回值:合并以后额新数组;
数组转字符串:
//1. join('-')
arr.concat()
参数:(连接符)
功能:所有数组用连接符连接在一起;
返回值:用某个连接符连接;
//1.1
参数:('')空
功能:所有数组连接在一起;
返回值:合并成字符串整体;
数组复制方法:
//1. slice(startindex,endindex)
参数1:(开始位置(包含),结束位置(不包含))
返回值:存放复制出来的元素的数组;
参数2:(开始位置)
返回值:存放开始位置复制出来的元素到结尾;
var arr2=[9,8,7,6];
console.log(arr2.slice(2,3)) //[7]
参数3:(开始位置,负数)
返回值:开始位置到倒数第几个位置
console.log(arr2.slice(2,-1)) //[7,6]
索引查询字符:
// 1. ary.indexOf('zhi',2)
//调用次数:数组内的元素个数
// - 返回某个值第一次出现的索引号;
// - 如果数组中没有该值返回-1;
// - 如果后面加上数字如2,则是返回第二次出现的该值索引号
//2. lastIndexof
作用:返回一个元素在数组中最后次出现的位置
参数:元素
返回值:位置--找 不到返回-1
vararr3=[5,6,7,5]
console . log(arr3. indexof(5));//0
console. log(arr3.lastIndex0f(5));//3
console .1og(arr3 . index0f(100));//-1
数组内包含否:
//1. includes`
功能:判断是否包含一个元素
參数:是一个元素
返回值: true或者false
语法:arry.includes('str');
const array1 = [1, 2, 3];
console.log(array1.includes(2));
// Expected output: true
const pets = ['cat', 'dog', 'bat'];
console.log(pets.includes('cat'));
// Expected output: true
数组遍历
-
for()循环
for(var i =0 ;i< arr.length ;i++){ }
-
for() in{} 遍历
for( var i in arr){ i 元素的下标 }
遍历对象
for(var key in obj){ key 是属性名 } //案例: //遍历对象 var obj = { name: ' zhangsan', age: 18 }; for (var key in obj) { console. log(key);//属性名 j console.log(obj[key])//属性值 console.log(obj.key)//无法获取属性值,key此处是字符串,而不是变量名; }
-
for() of {} 遍历
for(var v of arr){ v 元素值 }
案例:数组练习
1. 山上有一口缸可以装50升水,现在有15升水。老和尚叫小和尚下山挑水,每次可以挑5升。问:小和尚要挑几次水才可以把水缸挑满?通过编程解决这个问题。
2. 定义一个含有30个整型元素的数组,按顺序分别赋予从2开始的偶数;然后按顺序每五个数求出一个平均值,放在另一个数组中并输出。试编程。
3. 通过循环按行顺序为一个5×5的二维数组a赋1到25的自然数,然后输出该数组的左下半三角。试编程。
堆栈
-
栈内存(基本类型)
- 较小,简单类型
- 存储简单数据类型:String,Number,Boolean,Null,Undefined
-
堆内存(引用类型)
- 较大,复杂类型
- 存储对象类型:Function,Array,Object
-
传递:
-
值传递
c=a; //表示将a的值传给c,而不是c传给a;
-
地址传递
obj=obj2 //将obj2的地址传递给obj
-
-
案例加练
数组–ES5(8)
forEach
- 功能:类似封装遍历
- 参数:函数;
- 特殊的:(遍历可以在中途i–),forEach不能;
// 2.
ary.forEach(function(e,index,arr){
console.log(e);//返回值;
console.log(index);//返回索引号
console.log(arr);//返回原视数组
})
// - 传入函数
var ary=[1,'q','a','b'];
ary.forEach((e,index,ary)=>{
console.log(e);
// console.log(index);
// console.log(ary);
// console.log(e+2);//3 q2 a2 b2
})
// - ans:1 0 Array(4) q 1 Array(4) 。。。。
// - forEach不能使用return ?
// - 输出过程中也可以参加运算
map
- 功能:遍历并操作,映射;
- 参数:函数;
- 特殊的:需要返回值;
// 3. map
var newAry=ary.map(function(e,index,ary){
console.log(e,index,ary)// item某个数,该数所处索引号,被处理的原数组
return e + 10 //不同于forEach;
})
console.log(newAry);//[11,12,13]
// - return 返回值操作后的值;
// - 操作:加减乘除等逻辑运算;
// - 需要创建一个新的变量来接收新数组,类似匿名函数;
// - map 不同与forEach() 可以 返回结果 return adsf; 并生成一个新数组;
filter
- 功能:遍历并过滤所有满足条件的元素,过滤;
- 参数:函数;
// 4. filter 返回满足的所有值组成的新数组
var newAry2=ary.filter(function(e,index,ary){
// return e+10//返回 1 q a b
// return e-10//返回1 什么原理????????
return e==1
})
console.log(newAry2);
// - 返回的是满足条件的值组成的新数组(条件只能是比较运算符吗?)
// - 不改变原来数组;
// 4.1
var arr2=[{name:'zhangsan',age=18},
{name:'zhangsan',age=11},
{name:'zhangsan',age=28}
]
var f2=arr2.filter(function(v){
return v.age >=18
})
// 4.2
//如果想要改变原始数组,用新数组覆盖掉原始数组;
every
- 功能
some
- 功能:查找至少有一个满足条件返回true;
// 5. some 返回布尔值
var newAry3=ary.some((e,index,ary)=>{
// return e===1 //true
return e=='q'//true
})
console.log(newAry3);
// 返回的是布尔值,数组内其中至少一个为真则会返回true
find
- 返回满足条件的第一个值;
// 6. find 返回第一个值
var arr6=[1,2,3,4,5,5,6,6];
var newA6=arr6.find((e)=>return e>3);
console.log(newA6);
// - 返回的是满足条件的第一个数值,不会返回全部;
findIndex
- 返回索引号一个
// 7. findIndex 返回第一个值的索引号
var newA6=arr6.findIndex((e)=> {return e>5})
console.log(newA6);//6
reduce
- 初始值;function(){},3 后面的值3
- 数组值;b
- 累计变量; a0=3 a0+b;
// 8. reduce
let res9 = arr6.reduce(function (a, b) {
console.log(a, b);
//a 是累积变量 ,1000就是累积变量的初始值
// b 是数组的元素
return a + b;
}, 1000)
console.log(res9);
// reduce(回调函数,变化的初始数值)
// 过程中 a 为初始值与数组每个值的变化后结果;b为每个数组的值;return 后面重复变化的式子
// - 类似回调函数
案例–es5筛选
var employees = [
{name: 'A', sex: '男', age: 21, salary: 10000},
{name: 'B', sex: '女', age: 25, salary: 12000},
{name: 'C', sex: '男', age: 24, salary: 13000},
{name: 'D', sex: '男', age: 24, salary: 12500},
{name: 'E', sex: '女', age: 21, salary: 14000},
{name: 'F', sex: '男', age: 24, salary: 16000},
{name: 'G', sex: '男', age: 23, salary: 9000},
{name: 'H', sex: '女', age: 21, salary: 11000},
{name: 'I', sex: '男', age: 23, salary: 13200},
{name: 'J', sex: '男', age: 23, salary: 15000}
]
/*
公司前后招聘了10个员工(性别,年龄, 月薪各不相同),有以下需求
1). 列表显示所有员工的所有信息
2). 对员工进行年薪降序列表显示
3). 得到男员工的总月薪
4). 查找一个月薪只比12000高一点点的员工
5). 查找出所有月薪高于12000的员工
6). 删除年龄是21的元素(过滤出年龄不是21的元素)
*/
复习
- 二维数组
- 堆和栈
- 值传递和引用传递
- 高阶方法:
- 不改变
- forEach
- map
- filter
- some
- every
- find
- findIndex
- reduce
- 不改变
数组去重
//includes
function norepeat(ary) {
var newAry =[];
for (var k of ary) {
if (newAry.includes(k) == false) {
newAry.push(k)
}
}
return newAry
}
//indexOf
function norepeat2(ary){
var newAry=[];
for( var k of ary){
if(newAry.indexOf(k)===-1){
newAry.push(k)
}
}
return newAry
}
//splice
function norepeat3(arr){
for (var i=0 ;i<arr.length;i++){
// if(arr.indexOf(arr[i]!=i)){//arr[i]!=i 说明索引号上的值外还有其他;,因此删除
// arr.splice(i,1);
// }
// console.log(arr.indexOf(arr[i])) //indexOf内部的字符此处是灵活的;
//如果是灵活的arr[i]出现重复,由于查找第一个值则会输出相同的索引号;//因此需要裁剪掉;
if(arr.indexOf(arr[i])!=i){
arr.splice(i,1);
i--;//i需要再操作之后回退一格,容易忘记;
}
}
return arr;
}
// filter
var res1 = arr. filter(function (V, i) {
// v第一次出现的下标和v的下标一致
return arr . indexOf(v) == i
});
console. log(res1);
// reduce
排序
- 冒泡
1. - 选择
- var j=min 翻视频重看;2 lived
## 字符串基础
-
创建 str=‘123’ 字面量写法;
-
单引号
-
反引号
-
双引号
-
构造函数创建
var strObj =new String('hello'); 生成字符串对象; log(strObj) 可以展开; 伪数组类型; 字符串对象可以当字符串使用; 字符串可以当成字符串对对象作用; length属性 字符串的长度;
-
-
反引号 (模板字符串)
- 可以换行
~ 这是一个${变量名}字符串~ 等价于 'Rong'+'zhou'
字符串方法(16)
- 所有的字符串方法都会修改原始字符串,返回值是新的字符串;
concat(,)*
//功能:合并字符串
charAt(0)
//功能:索引号返回字符
var str='hello world'
str.charAt(index)
console.log(str.charAt(11));//''
//1. 没有该索引号返回空--''
//2. 存在返回索引
3. console.log(str[11]);
//数组越界--undefined--使用对象不存在的属性--值就是undefined
indexOf(‘str’)*
//功能:查找一个字符串,在str中第一次出现的下标;
lastIndexOf(‘str’)*
//功能:查找一个字符串, 在str中最后一次出现的下标
includes(‘str’)*
//功能:查找一个字符串 在str中 是否包含 **
substring(slice*)
//功能:复制字符串;
//语法:str.substring(索引start,索引end(不包含))
//语法:ary.slice(索引start,索引end(不包含))
//参数:若省略第二个参数,会从开始截取到最后;
//原字符串:不改变字符串本身
var str2 = 'hello world';
var res2 = str2.substring(2, 7);
console.log(res2);//llo
console.log(str2);//hello world-- 不改变字符串本身
//参数:负数;
//不同与slice;
待完善;
tips: substring 长的比较长把单词写完了所以叫做复制;
substr()
//截取字符串
//语法:substr(从哪个索引开始,截取多少个)
var str3 = 'hello world';
console.log(str3.substr(2, 2));
//不改变原有字符串
tips: substr 长得比较短单词只写了半截所以叫做截取;
而且都使用str标注了这两者都是str的字符串方法;
toLowerCase
//功能:全部字符串转小写;
var str4 = 'Hello';
console.log(str3.toUpperCase());//HELLO WORLD
toUpperCase
//功能:全部字符串转大写;
console.log(str2.toLowerCase());//hello world
replace
//功能:替换遇到的第一个匹配的内容
//语法:replace('要替换的内容','替换成什么')
var str5 = '你是垃圾吗,垃圾';
var res5 = str5.replace('垃圾', '**');
console.log(res5);//你是**吗,垃圾
console.log(str5);//你是垃圾吗,垃圾
replaceAll()
//功能:替换所有匹配的内容
//语法:replace('要替换的内容','替换成什么')
split()
//功能:按照分割符将字符串分割为数组;
//语法:split('-')
//参数1:分隔符
var str7 = 'a-b-caa-d';
var arr7 = str7.split('-')
console.log(arr7);//['a', 'b', 'caa', 'd']--删除了横线
//参数2:空字符串
var str7.split('');//['a', '-', 'b', '-', 'c', 'a', 'a', '-', 'd']
trim()
//功能:首尾去空格;
console.log(' aaa bb '.trim());//aaa bb
charCodeAt(0)
//功能:将对应编号的字符换成计算机能够识别的编码
var str = 'a你';
console.log(str.charCodeAt(0));//97
fromCharCode(,)
//功能:将编码转为字符串
var r = String.fromCharCode(97, 98)
console.log(r);
案例–字符串
// 1. 随机生成一个五位以内的数,然后输出该数共有多少位,每位分别是什么
// 2. 敏感词过滤.
// 3. 数字字母混合6位验证码
// 4. 已知字符串“a,a,b,c,c,d”,统计每个字符出现的次数,结果显示 a 2、b 1、c 2、d 1。
- 面试题;
ASCLL码
-
完整名:(American Standard Code for Information Interchange):
-
美国信息交换标准字符集
-
万国码
复习
-
数组去重
- filter/reduce/indexOf
-
冒泡/选择
-
字符串
- 创建
- 单引号
- 双引号
- 反引号
- 构造函数
- 方法
- indexOf
- slice
- toUpperCase
- replace
- replaceAll
- split
- trim
- 创建
Math对象及方法
- Math 是 js 的一个内置对象,提供了一堆的方法帮助我们操作 数字
- 操作数字的方法;
Math.random()
-
伪随机数:0<=r<1
-
技巧案例
//生成 0-20 的随机数; //生成 2-9 的随机数;
Math.round()
-
四舍五入,保留整数;
-
注意:无论正负;五入,大于本身的最小值;x轴正方向
-
相似的 toFixed()
// 1. var num0=-1.4; var num1=-1.5; var num3=1.5; console.log(Math.round(num0));//-1 console.log(Math.round(num1));//-1 !=-2 console.log(Math.round(num3));//2 // 2. // (num.toFixed(num) // 保留几位小数-- 结果为字符串 console.log(num.toFixed(3));
Math.ceil()
-
向上取整(比参数大的最小整数)
console.log(Math.ceil(-1.5)); //-1 console.log(Math.ceil(-1.4)); //-1
Math.floor()
-
向下取整(比参数小的最大整数)
console.log(Math.floor(-11.1));//-12
Math.abs()
-
返回一个数字的 绝对值
-
原理
function abs(num) { if (num > 0) return num; else return -num; }
Math.PI()
console.log(Math.PI());
Math.max()
-
Math.max()` 得到的是你传入的几个数字之中 最大 的那个数字
//1. 基础; console.log(Math.max(1, 2, 3));//3 //2. 数组; var arr = [4, 5, 6, 7] console.log(Math.max(arr));//NaN //2.1 console.log(Math.max([]));//0 //2.2 console.log(Math.max(...arr));//7 扩展运算符 //2.3 console.log(Math.max(...[]));//-Infinity 负无穷 //原理:函数封装首先使用一个最小值作为初始值,再不断比较;因此返回的是最小值;
Math.min()
-
Math.min()` 得到的是你传入的几个数字之中 最小 的那个数字
console.log(Math.min(a, b, c)); console.log(Math.min(...arr)); console.log(Math.min(...[]));//Infinity
Number.MAX_VALUE()
Number.MAX_VALUE()
Math.pow()
- 次方;
pow(2,10) 求2的10次方
console.log(Math.pow(2, 10));
console.log(2 ** 10);
Math.sqrt()
-
开方(算数平方根)
console.log(Math.sqrt(4));//2
Math.sin()
-
求某个弧度的正弦值
-
弧度与角度的换算
// 角度 * Math.PI/180 -- 角度对应的弧度 console.log(Math.sin(30 * Math.PI / 180)); console.log(Math.sin(30 * Math.PI / 180).toFixed(3));
案例–Math
1. 编写一个函数,能够获得一个随机的 0 ~ 255 之间的数字(包含 0 和 255)
2. 编写一个函数,能够获得一个随机的 min~ max 之间的数字
3. 随机16进制颜色字符串//应用;
Date构造函数(没写)
Math对象
- Math.max(…arr) 展开数组;
- Math.max(…[])//-infinity;
Math.max原理:用一个初始值(最小的值)记录作为最大值,然后依次比较;
BOM
dom 与bom的区别;
-
ECMAScript是js的规范,dom是获取html元素,bom是操作html的方法;
-
window对象,事件,方法解释:
-
基础三大事件:鼠标,键盘,html
-
BOM对象方法分类合集:
-
事件对象方法属性的区别;
- 事件是特殊的方法:强调一种改变,事件发起者与响应者的数据关联;
- 方法可能只是中间的过程;
-
BOM定义
-
定义:BOM 是 Browser Object Model,浏览器对象模型**。BOM 是为了控制浏览器的行为而出现的接口**。
:BOM为JavaScript提供了一种控制浏览器行为的"方法"。
-
BOM包含DOM
-
构成:
-
具体操作内容(方法):
- 获取一些浏览器的相关信息(窗口的大小)
- 操作浏览器进行页面跳转
- 获取当前浏览器地址栏的信息
- 操作浏览器的滚动条
- 浏览器的信息(浏览器的版本)
- 让浏览器出现一个弹出框(alert/confirm/prompt)
- BOM 的核心就是 window 对象
- window 是浏览器内置的一个对象,里面包含着操作浏览器的方法
window对象
- window对象:JS的最顶层对象,其他的BOM对象都是window对象的属性;
属性
- 全局,声明的变量
- 全局,this的指向
- 属性-浏览器的宽高
html事件-窗口加载
-
分类:
-
window.onload
-
窗口(页面)加载事件
-
文档内容整个网页完全加载完成会触发该事件**(包括图像,脚本文件,CSS文件,下方的代码等)**,调用处理函数。
-
window.onload 传统注册事件方式,只能写一次
-
多个,以最后一个window.onload为准,qi按一个会被覆盖掉
与此类似的还有 ele.onlick=function(){}
-
-
DOMContentLoaded
- 窗口(页面)加载事件
- DOMCountentLoaded事件触发时,仅当DOM加载完成,不包括样式表,图片,flash等等
- 使用addEventListener 则没有限制
- 依次执行
-
-
共同点:
- 加载dom可以将js代码写到页面元素上方;
-
不同点:
- 由于加载内容样式表,图片等差异,导致加载速度的DOMContentLoaded较快,适合再图片多的场景使用,节约访问时间,提高用户体验;
- 写的次数
//传统注册事件 window.onload = function(){ }; // or window.addEventListener("load",function(){}); //add监听注册 window.addEventListener('DOMContentLoaded',function(){})
-
注意:i8以下不支持addEventListener(‘DOMContentLoaded’,function(){})
html事件-调整窗口大小
-
window.onresize;
-
定义:窗口大小发生像素变化,就会触发这个事件
-
场景:利用这个事件完成响应式布局。window.innerWidth 当前屏幕的宽度
window.addEventListener('load', function() { var div = document.querySelector('div'); window.addEventListener('resize', function() { console.log(window.innerWidth); console.log('变化了'); if (window.innerWidth <= 800) { div.style.display = 'none'; } else { div.style.display = 'block'; } }) })
-
html事件-页面滚动
-
window.onscroll(窗口滚动执行)
window.onscroll = function () { console.log('浏览器滚动了') }
注意:前提是页面的高度要超过浏览器的可是窗口才可以
scroll属性
-
后期与client,scroll,offset一同介绍
-
//获取页面向上滚动的距离;
//document.body ==》 是body元素;
//document.documentElement.scrollTop ==>文档对像.html标签;
window.onscroll = function () {
console.log(document.documentElement.scrollTop)
var scollTop = document.documentElement.scrollTop
}
//设置scroll滚动条的距离;
document.documentElement.scrollTop = 0
方法-浏览器弹出层
-
prompt()
- 这个弹出层有一个输入框和两个按钮
- 当你点击取消的时候,得到的是 null
- 当你点击确定的时候得到的就是你输入的内容
-
alert()
- 这个弹出层知识一个提示内容,只有一个确定按钮
- 点击确定按钮以后,这个提示框就消失了
-
confirm()
- 这个弹出层有一个询问信息和两个按钮
- 当你点击确定的时候,就会得到 true
- 当你点击取消的时候,就会得到 false
var str = window.prompt('请输入内容') console.log(str) // window.alert('我是一个提示框') // var boo = window.confirm('我是一个询问框') console.log(boo)
方法-定时器
-
注意:
-
可以省略window;
-
这个调用函数:可以直接写函数或者写函数名或者采取字符串 ‘函数名()’ (不推荐)
-
延迟的毫秒数省略默认是0,如果写,必须是毫秒
-
因为定时器可能有很多,所以我们经常给定时器赋值一个标识符
-
-
setTimeout()
- setTimeout() 这个调用函数我们也称为回调函数 callback
- 普通函数是按照代码顺序直接调用,而这个函数,需要等待事件,事件到了才会去调用这个函数,因此称为回调函数。
// 语法规范:window.setTimeout(调用函数,[延迟的毫秒数]); // setTimeout(function() { console.log('时间到了'); }, 2000); // function callback() { console.log('爆炸了'); } var timer2 = setTimeout(callback, 5000); // setTimeout('callback()', 3000); // 不提倡这个写法
-
setInterval()
- setInterval()方法重复调用一个函数,每隔这个时间,就去调用一次回调函数
- 这个回调函数:可以直接写函数或者写函数名或者采取字符 ‘函数名()’
- 第一次执行也是间隔毫秒数之后执行,之后每隔毫秒数就执行一次
// 语法规范: window.setInterval(调用函数, 延时时间); setInterval(function() { console.log('继续输出'); }, 1000);
-
clearTimeout()
-
停止setTimeout定时器;
//clearTimeout()方法取消了先前通过调用 setTimeout()建立的定时器 window.clearTimeout(timeoutID)
<body> <button>点击停止定时器</button> <script> var btn = document.querySelector('button'); var timer = setTimeout(function() { console.log('爆炸了'); }, 5000); btn.addEventListener('click', function() { clearTimeout(timer); }) </script> </body>
-
-
clearInterval()
-
停止setInterval定时器;
<body> <button class="begin">开启定时器</button> <button class="stop">停止定时器</button> <script> var begin = document.querySelector('.begin'); var stop = document.querySelector('.stop'); var timer = null; // 全局变量 null是一个空对象 begin.addEventListener('click', function() { timer = setInterval(function() { console.log('ni hao ma'); }, 1000); }) stop.addEventListener('click', function() { clearInterval(timer); }) </script> </body>
-
this指向
-
this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁
-
现阶段,我们先了解一下几个this指向:
-
全局作用域或者普通函数中this指向全局对象
-
window(注意定时器里面的this指向window)
-
方法调用中谁调用this指向谁
-
构造函数中this指向构造函数实例
<body> <button>点击</button> <script> // this 指向问题 一般情况下this的最终指向的是那个调用它的对象 // 1. 全局作用域或者普通函数中this指向全局对象window( 注意定时器里面的this指向window) console.log(this); function fn() { console.log(this); } window.fn(); window.setTimeout(function() { console.log(this); }, 1000); // 2. 方法调用中谁调用this指向谁 var o = { sayHi: function() { console.log(this); // this指向的是 o 这个对象 } } o.sayHi(); var btn = document.querySelector('button'); // btn.onclick = function() { // console.log(this); // this指向的是btn这个按钮对象 // } btn.addEventListener('click', function() { console.log(this); // this指向的是btn这个按钮对象 }) // 3. 构造函数中this指向构造函数的实例 function Fun() { console.log(this); // this 指向的是fun 实例对象 } var fun = new Fun(); </script> </body>
location对象
- 定义:浏览器当前URL信息;
url:
-
定义:统一资源定位符(uniform resouce locator)是互联网上标准资源的地址。互联网上的每个文件都有一个唯一的 URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它。
-
语法格式:
protocol://host[:port]/path/[?query]#fragment http://www.itcast.cn/index.html?name=andy&age=18#link
组成 | 说明 |
---|---|
protocol | 信协议 常用的http,ftp,maito等 |
host | 主机(域名) www.itheima.com |
port | 端口号,可选 |
path | 路径 由零或多个’/'符号隔开的字符串 |
query | 参数 以键值对的形式,通过&符号分隔开来,通过 ? 来开头 |
fragment | 片段 #后面内容 常见于链接 锚点 |
origin | 来源,网站开头 |
属性
location对象属性 | 返回值 |
---|---|
location.href *** | 获取或者设置整个URL |
location.host | 返回主机(域名)www.baidu.com |
location.port | 返回端口号,如果未写返回空字符串 |
location.pathname*** | 返回路径 |
location.search *** | 返回参数 |
location.hash *** | 返回片段 #后面内容常见于链接 锚点 哈希值 |
方法
location对象方法 | 返回值 |
---|---|
location.assign() | 跟href一样,可以跳转页面(也称为重定向页面),可以返回 |
location.replace() | 替换当前页面,因为不记录历史,所以不能后退页面 |
location.reload()*** | 重新加载页面,相当于刷新按钮或者 f5 ,如果参数为true 强制刷新 ctrl+f5 |
reload 注意: 不要写在全局,不然浏览器就会一直处在刷新状态,类似死循环
通常配合按钮使用;
window.location.replace("c.html");
<body>
<button>点击</button>
<div></div>
<script>
var btn = document.querySelector('button');
var div = document.querySelector('div');
var timer = 5;
setInterval(function() {
if (timer == 0) {
location.href = 'http://www.itcast.cn';
} else {
div.innerHTML = '您将在' + timer + '秒钟之后跳转到首页';
timer--;
}
}, 1000);
</script>
</body>
跳转案例
- 功能:点击登录跳转到index.html
/*login 页面:*/
<body>
<form action="index.html">
用户名: <input type="text" name="uname">
<input type="submit" value="登录">
</form>
</body>
/*index.html*/
<body>
<div></div>
<script>
console.log(location.search); // ?uname=andy
// 1.先去掉? substr('起始的位置',截取几个字符);
var params = location.search.substr(1); // uname=andy
console.log(params);
// 2. 利用=把字符串分割为数组 split('=');
var arr = params.split('=');
console.log(arr); // ["uname", "ANDY"]
var div = document.querySelector('div');
// 3.把数据写入div中
div.innerHTML = arr[1] + '欢迎您';
// 这样我们就能获取到路径上的URL参数
</script>
</body>
navigator对象
属性
-
navigator.userAgent:用户代理:
-
该属性可以返回由客户机发送服务器的user-agent头部的值
-
使用场景:判断用户是用哪个终端打开页面的,如果是用 PC 打开的,我们就跳转到 PC 端的页面,如果是用手机打开的,就跳转到手机端页面
if((navigator.userAgent.match(/(ph one|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i))) { window.location.href = ""; //手机 } else { window.location.href = ""; //电脑 }
-
判断2
console.log(window.navigator.userAgent) // Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36 console.log(navigator.userAgent) if(navigator.userAgent.toLowerCase().indexOf('windows')!=-1){ console.log('window pc') }else{ console.log('移动端') if(navigator.userAgent.toLowerCase().indexOf('iphone')!=-1 || navigator.userAgent.toLowerCase().indexOf('ipad')!=-1){ console.log('ios') }else{ console.log('安卓') } }
-
screen对象
属性
- onscroll
- width
- height
history对象
-
定义:window 对象给我们提供了一个 history 对象,与浏览器历史记录进行交互
-
该对象包含用户(在浏览器窗口中)访问过的 URL。
history方法
history对象方法 | 作用 |
---|---|
back() | 后退功能,回退历史记录,到前一个页面,相当于浏览器上的 ⬅️ 按钮 |
forward() | 前进功能 |
go(参数) | 前进后退功能,参数如果是 1 前进1个页面,如果是 -1 后退1个页面 |
//
window.history.back()
//
window.history.forward()
history.go(1)
//
history.go(-1)
//前提是你要有上一条记录,不然就是一直在这个页面,也不会回退
本地存储Html5新增
-
定义:
- 本地存储:(硬盘)
- 内存存储:(临时性存储) js变量
-
分类
-
window.sessionStorage (会话存储)
-
生命周期:关闭浏览串口;
-
同一个窗口数据共享
-
键值对的形式存储使用
存储数据:sessionStorage.setItem(key, value) 获取数据:sessionStorage.getItem(key) 删除数据:sessionStorage.removeItem(key) 删除所有数据:sessionStorage.clear()
-
-
window.localStorage (本地存储)
- 永久生效,除非手动删除,关闭也会存在;
- 多窗口页面共享(同一浏览器)
- 键值对形式存储使用
存储数据:localStorage.setItem(key, value) 获取数据:localStorage.getItem(key) 删除数据:localStorage.removeItem(key) 删除所有数据:localStorage.clear()
localStorage.setItem("b","isaac");//设置b为"isaac" var b = localStorage.getItem("b");//获取b的值,为"isaac" localStorage.removeItem("b");//清除c的值 localStorage.clear();//清除当前域名下的所有localstorage数据
-
DOM
DOM树
-
定义:DOM(Document Object Model ,文档对象模型)一种独立于语言,用于操作xml,html文档的应用编程接口。
对于JavaScript:为了能够使JavaScript操作Html,JavaScript就有了一套自己的DOM编程接口。
-
dom对象:
- 文档:一个页面就是一个文档,DOM中使用document表示
- 元素:页面中的所有标签都是元素,DOM中使用element表示
- 节点:网页中的所有内容都是节点(标签、属性、文本、注释等),DOM中使用node表示
获取元素
特殊元素获取:
console.log(document);
console.log(document.body);
console.log(document.documentElement);
id获取:
1. 返回单个对象:
//1.id
document.getElementById('id')
//2. 选择器
document.querySelector('.box');//H5新增
标签/类获取:
- 返回伪数组装的对象集合形式:
- 无内容返回空数组:
- 动态得到,想要操作元素需要遍历
//2. 类名
console.log(document.getElementsByClassName('lis')); //H5新增
//3. 标签
console.log(document.getElementsByTagName('input'));
//4. 选择器
console.log(document.querySelectorAll('.lis'));//所有//H5新增
HTML5新增获取
document.querySelector('.box');//H5新增
console.log(document.querySelectorAll('.lis'));//所有//H5新增
console.log(document.getElementsByClassName('lis')); //H5新增
操作元素
样式属性操作
-
获取
var text1 = box.innerHTML//识别换行,标签 W3C标准保留空格和换行,推荐 var text2 = box.innerText//纯文本,标签作字符串输出 非标准去除空格和换行 var iptText = ipt.value//表单内容 console.log(text1,text2,iptText);
属性是可读写的,可以获取元素里面的内容
-
赋值
box.innerHTML='一段文本';
-
样式
box.style.color = 'red'; // - 带横线的改驼峰 box.style.backgroundColor = 'blue'; // box.style.backgroundPositionY = i+'px'; // img.src = 'images/ldh.jpg'; img.title = '张学友思密达'; // btn.disabled = true;
样式修改:包括ele.style or ele.className;
类名样式操作
-
增删改查
box.className='clicked';// 覆盖 ~~~~~~~~js // - 增/改/删/换 // 争对某个 box.classList.add('color'); box.classList.replace('color','weight'); box.classList.remove('clicked'); box.classList.toggle('style2'); ~~~~~~~~
其他标准属性操作
- (标签有的属性都可选中)
var radio = document.querySelector('.radio')
var img = document.querySelector('.img');
radio.checked = 'checked';
ipt.type = 'password';
console.log(img);
// img.src ='http://qfcd.bj.bcebos.com/v1/%2Fimg%2F2023-06-01/cod.png';
自定义属性操作
<div id='box' sing='song' index='0'></div>
//获取自定义属性
bDiv.getAttribute('bbb')
//设置自定义属性
bDiv.setAttribute('key','value')
//删除自定义属性
bDiv.removeAttribute('aaa')
//切换自定义属性
bDiv.toggleAttribute('data-index');
// 获取 data-xx 属性的方法
data-id="2323" 专门用来的存数据的属性
// 1.
console.log(bDiv.getAttribute('data-id'));
console.log(bDiv.dataset.id);
// 2.
console.log(ele.dataset.index)
// 3.
console.log(ele.dataset['index']) //ie 11 以上
统一规定自定义属性以data-开头作为并赋值
DOM案例
案例–留言板
案例–选项卡
className选项卡
classList选项卡
tab切换选项卡
案例–鼠标移入移出
节点获取
- 元素的获取通常使用dom提供方法,节点操作的方法
//dom--逻辑性弱,繁琐
document.getElementById()
//节点--逻辑性强
parent
children
sibling
- 网页中的所有内容都是节点(标签、属性、文本、注释等),在DOM 中,节点使用 node 来表示。HTML DOM 树中的所有节点均可通过 JavaScript 进行访问,所有 HTML 元素(节点)均可被修改,也可以创建或删除。
节点属性
-
分类:
- 元素节点
- 属性节点
- 文本节点
- 包含文字,空格,换行
-
属性:
- nodeType 元素–1 属性–2 文本–3 (记忆顺序,一次向内收);
- nodeName 获取节点的名 等价于属性名
- 元素节点的
nodeName
就是 大写标签名 - 属性节点的
nodeName
就是 属性名 - 文本节点的
nodeName
都是 #text
- 元素节点的
- nodeValue 获取节点的值
- 元素节点没有
nodeValue
- 属性节点的
nodeValue
就是 属性值 - 文本节点的
nodeValue
就是 文本内容
- 元素节点没有
// console.log(eleNode.nodeType) // 1 console.log(attrNode.nodeType) // 2 console.log(textNode.nodeType) // 3 // console.log(eleNode.nodeName) // LI console.log(attrNode.nodeName) // test console.log(textNode.nodeName) // #text // console.log(eleNode.nodeValue) // null console.log(attrNode.nodeValue) // 我是 ul 的一个属性 console.log(textNode.nodeValue) // 换行 + 空格
节点层级
-
父节点
-
返回某节点的父节点,最近的一个
node.paretNode node.parentElement;
-
子节点
- 返回包含指定节点的子节点集合,包含所有类型的界定啊,元素节点,文本节点,属性节点。
parentNode.childNodes(标准)
//不推荐
- 只读属性,返回所有的子元素节点
parentNode.children(非标准)
//推荐,各个浏览器支持
- 其他的
// 包含所有的节点类型 parentNode.firstChild // parentNode.lastChild // // 只包含元素节点类型( 有兼容性问题 ie9以上支持) parentNode.firstElementChild // parentNode.lastElementChild ~~~~~~~~~~~~~~~~
-
兼容性问题的解决
//第一个子元素节点 parentNode.children[0] //摸一个子元素节点 parentNode.children[parentNode.children.length-1]
-
兄弟节点
- 返回当前元素的下一个兄弟节点,找不到返回null,包含所有类型节点;
node.nextSibling;
- 返沪当前元素的前一个兄弟节点,找不到返回null,包含所有类型节点;
node.previousSibling;
- 返回当前元素下一个兄弟元素节点,找不到则返回null
node.nextElementSibling;//兼容 ie9以上
- 返回当前元素上一个兄弟节点,找不到则返回null
node.previousElementSibling;//兼容 ie9以上
节点操作
-
创建
//createElement var li = document.createElement('li'); //createTextNode var oText = document.createTextNode('我是一个文本');
-
添加
// 1. 法一 parentNode.appendChild(li);//向父节点中追加一个文本节点 // 2. 法二 parentNode.insertBefore(li,某子元素)//向父元素节点中的某一个节点签方插入一个节点; //使用 ul.appendChild(li); ul.insertBefore(li,ul.lastElementChild)
-
修改
//语法: parentNode.replaceChild(newNode,oldNode); //使用: <div> <p>我是p标签原来内部的内容</p> </div> var div = document.querySelector('div'); var op = document.querySelector('p'); var nSpan = document.createElement('span'); nSpan.innerHTML ='我是新创建的span标签中的内容部分'; div.replaceChild(nSpan,op);
-
删除
// 子元素在内 ul.removeChild(li); // 子元素在外 li.remove();
-
复制(克隆)
事件基础
-
定义:js使我们能有能力创建动态页面,事件则是被js检测到的行为;
-
触发:每个元素都可以产生某些可以触发js的事件,例如,我们可以在用户点击按钮时产生一个事件,然后去执行某些操作 。
事件三要素
-
要素
- 事件源(谁)
- 事件类型(什么事件)
- 事件处理程序(做啥)
-
步骤
-
获取事件源
-
注册事件(绑定事件)
-
添加事件处理程序(采取函数赋值形式)
事件对象使用语法
- 定义:event对象代表事件的状态,比如键盘按键的状态、鼠标的位置、鼠标按钮的状态
- 通俗:事件相关的一系列信息数据的集合都放到这个对象里面,这个对象是事件对象event,它有很多属性和方法
eventTarget.onclick = function(event) {}
eventTarget.addEventListener('click', function(event) {})
// 这个 event 就是事件对象,我们还喜欢的写成 e 或者 evt
兼容性方案
解决:
e = e || window.event;
-
事件对象本身获取存在兼容问题;
-
标准浏览器中:传递形参 e ,只需要定义形参e可以获取到;
div.addEventListener('click', function(e) { console.log(e); })
-
ie 6 ~ 8中,浏览器不会给方法传递参数,需要手动window.event中获取查找
解决: e = e || window.event;
-
事件对象常用属性/方法

-
e.target 与this的区别
-
this 是事件绑定的元素,e.target这个函数的调用者(绑定这个事件的元素)
事件委派用该特点比较多
例子,给父元素绑定点击事件;触发该事件的父元素的子元素e.target(li),而绑定者为this(父元素)
-
监听事件
-
eventTarget.addEventListener()
btn.addEventListener('click',function(){},[true/false]) eventTarget.addEventListener(type, listener[, useCapture])
事件类型,监听函数,可选参数(默认false)
第三个参数如果是 true,表示在事件捕获阶段调用事件处理程序;如果是 false(不写默认就是false),表示在事件冒泡阶段调用事件处理程序
-
eventTarget.attachEvent()
btn.attachEvent('onclick',function(){}) eventTarget.attachEvent(eventNameWithOn, callback)
-
注册事件兼容性解决方案
function addEventListener(element, eventName, fn) { // 判断当前浏览器是否支持 addEventListener 方法 if (element.addEventListener) { element.addEventListener(eventName, fn); // 第三个参数 默认是false } else if (element.attachEvent) { element.attachEvent('on' + eventName, fn); } else { // 相当于 element.onclick = fn; element['on' + eventName] = fn; } }
解绑事件
- 传统
- eventTarget.onclick = null;
- 监听
- eventTarget.removeEventListener(type, listener[, useCapture]);
- eventTarget.detachEvent(eventNameWithOn, callback);
//1.
divs[0].onclick = function() {
alert(11);
// 1. 传统方式删除事件
divs[0].onclick = null;
}
//2.
// 2.1 removeEventListener 删除事件
divs[1].addEventListener('click', fn) // 里面的fn 不需要调用加小括号
function fn() {
alert(22);
divs[1].removeEventListener('click', fn);
}
// 2.2 detachEvent
divs[2].attachEvent('onclick', fn1);
function fn1() {
alert(33);
divs[2].detachEvent('onclick', fn1);
}
- 删除事件兼容性解决方案
function addEventListener(element, eventName, fn) {
// 判断当前浏览器是否支持 addEventListener 方法
if (element.addEventListener) {
element.addEventListener(eventName, fn); // 第三个参数 默认是false
} else if (element.attachEvent) {
element.attachEvent('on' + eventName, fn);
} else {
// 相当于 element.onclick = fn;
element['on' + eventName] = fn;
}
}
事件流
-
DOM事件流定义:事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程即DOM事件流
-
事件冒泡:IE 最早提出,事件开始时由最具体的元素接收,然后逐级向上传播到到 DOM 最顶层节点的过程。
-
事件捕获:网景最早提出,由 DOM 最顶层节点开始,然后逐级向下传播到到最具体的元素接收的过程。
-
实际开发很少使用捕获,关注冒泡多一些;
-
案例:
比如:我们给DIV添加了点击事件 DOM事件流分为3个阶段 捕获阶段 当前目标阶段 冒泡阶段 冒泡的使用场景:触发儿子添加的事件,父节点的添加事件也被触发(冒上来的)
冒泡案例分析
儿绑父绑
let big = document .querySelector( .big”)
let center = document.querySelector('.center' )
Let small = document.querySelector( ' . small' )
big.addEventListener('click', () => {
console.log 'big')
})
center.addEventl istener('click', () => {
console.log ' center' )
})
small.addEventlistener('click', () => {
console.log ' small')
})

click small box
click center box
click big box
父亲未绑
- 如果父元素没有绑定点击事件则只会触发点击盒子的事件。
Let big = document . querySelector(' .big' )
let center = document . queryselector(' . center' )
Let small = document . querySelector(' . smal1')
// big. addEventlistener( 'click', () => {
//
console. log( 'big')
// })
// center. addEventListener( 'click', () => {
// console. log( 'center')
// })
small. addEventlistener('click', () => {
console. Log( ' small' )
})
click small box
儿子未绑
- 如果子元素(
small
)的点击事件去掉,当我们点击small
的时候会把当前操作的点击事件传递给父元素(因为父元素绑定了点击函数)
let big = document .queryselector( .big ' )
Let center = document . querySelector( ' . center' )
let small = document . querySelector(' .small')
big . addEventlistener('click', () => {
console.log('big')
})
center . addEventl istener('click', () => {
console. Log (' center')
})
// small . addEventL istener( 'click', () => {
// console. Log( 'small')
// })
click small box
- 没有冒泡事件:onblur,onfocus,onmouseenter,onmouseleave,onclick,attachEvent;(addEventListener:则需要关注false(表示冒泡),true)
- 冒泡事件麻烦:nav导航栏的蹦迪事件
- 冒泡事件优势:少写点步骤;
阻止冒泡
-
e.stopPropagation() // 标准
-
e.cancelBubble = true; //非标准
-
兼容性问题解决
if(e && e.stopPropagation){ e.stopPropagation(); }else{ window.event.cancelBubble = true; }
应用–阻止默认
- 鼠标右键菜单
- 鼠标选中
事件委托
- 事件委托原理:
- 不是每个子节点单独设置事件监听器,而是事件监听器设置在其父节点上,然后利用冒泡原理影响设置每个子节点。
立即执行函数
- 作用:创建独立作用域,避免命名冲突问题;
(function(){})();
(function(){}());
DTD
-
使用:
<!DOCTYPE root-element [element-declarations]>
-
作用:
- 携带自身格式描述
- 团体交换数据
- 应用程序也可使用某个标准的 DTD 来验证从外部接收到的数据。
- DTD 来验证您自身的数据。
鼠标
事件
-
基本
项目 Value 冒泡 click 单击鼠标左键时发生,右键按下则不会发生。左键+ Enter 键,同样触发 dblclick 双击鼠标左键,如果右键也按下则不会发生 mousedown 鼠标按下 mouseup 鼠标弹起 mouseover 移入元素之间 mouseout 鼠标离开 mousemove 鼠标移动(持续触发) blur 失去焦点 无 focus 获得焦点 无 mouseenter 移入元素之间 无 mouseleave 鼠标离开 无
mouseenter 只会经过自身盒子触发,mouseover 鼠标经过自身盒子会触发,经过子盒子还会触发。
mouseleave 只会经过自身盒子触发,mouseout 鼠标经过自身盒子会触发,经过子盒子还会触发。
- 常见
-
右键菜单–contextmenu
document.addEventListener('contextmenu', function(e) { e.preventDefault(); })
-
鼠标选中–selectstart
document.addEventListener('selectstart', function(e) { e.preventDefault(); })
-
对象(属性)


键盘
事件
- 单个

-
组合
事件 Value 监听 ctrlKey true/false ctrl键与其他键组合 altlKey true/false alt键与其他键组合 shiftKey true/false shift键与其他键组合
- 如果使用addEventListener 不需要加 on
- onkeypress 和前面2个的区别是,它不识别功能键,比如左右箭头,shift 等。
- 三个事件的执行顺序是: keydown – keypress — keyup
对象(属性)

- onkeydown 和 onkeyup 不区分字母大小写,onkeypress 区分字母大小写。
- 实际开发使用多:keyup和keydown, 识别所有键(包括功能键)Keypress 不识别功能键(shift,alt,方向,ctrl,enter)。
- keyCode属性区分大小写,返回不同ASCII值。
- keydown 与keyup 区分主副数字键盘,可以使用功能键的组合效果
Ascall表
- ASCII码对照表 (oschina.net)
- 小写字母大于大写字母
系列
偏移量-offset
-
偏移量特点:
-
获得带有定位的父元素
-
获得自身的大小(宽高),包含border.
-
返回值不带单位
-
-
属性:

- 原理:

style对比
-
offset 只读;只有数值,包含border;
-
style可读可写;带单位,不包含border,padding;
可视区-client
-
作用:
- client 翻译客户端,获取元素可视区的相关信息。
-
属性:
-
原理:
滚动-scroll
- 原理:scroll 系列的相关属性可以动态的得到该元素的大小、滚动距离

- 属性:

兼容
-
场景:
- 声明了 DTD,使用 document.documentElement.scrollTop
- 未声明 DTD,使用 document.body.scrollTop
-
ie9支持:
- window.pageYOffset/window.pageXOffset
function getScroll() { return { left: window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft||0, top: window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0 }; } //使用的时候 getScroll().left
系列总结
-
属性对比
-
用法:
- offset系列经常用于获得元素位置 offsetLeftoffsetTop
- client经常用于获取元素大小 clientWidth clientHeight
- scroll经常用于获取滚动距离 scrollTop scrollLeft
- 注意页面的滚动距离通过window.pageXOffset获得
es6教程
let 和 const 命令 - ECMAScript 6入门 (ruanyifeng.com)
this的延时器定时器
1. 指向window;
es6 --let 和 const
- 在 ES6 的时候,多了两个关键字
let
和const
,也是用来声明变量的
-
特点:
- let
- 块级作用域
- 暂时性死区
- 同一块级作用域中不能重命名
- 没有变量提升
- const
- 赋值不能改变(命名时及必须赋值)
- 暂时性死区
- 没有变量提升
- let
-
和 var 区别
-
let
和const
不允许重复声明变量// 使用 var 的时候重复声明变量是没问题的,只不过就是后面会把前面覆盖掉 var num = 100 var num = 200
// 使用 let 重复声明变量的时候就会报错了 let num = 100 let num = 200 // 这里就会报错了
// 使用 const 重复声明变量的时候就会报错 const num = 100 const num = 200 // 这里就会报错了
-
-
let
和const
的区别- 声明的变量不会在预解析的时候解析(也就是没有变量提升)
// 因为预解析(变量提升)的原因,在前面是有这个变量的,只不过没有赋值 console.log(num) // undefined var num = 100
// 因为 let 不会进行预解析(变量提升),所以直接报错了 console.log(num) // undefined let num = 100
// 因为 const 不会进行预解析(变量提升),所以直接报错了 console.log(num) // undefined const num = 100
let
和const
声明的变量会被所在代码块限制作用范围(块级作用域)
// var 声明的变量只有函数能限制其作用域,其他的不能限制 if (true) { var num = 100//全局变量 } console.log(num) // 100
// let 声明的变量,除了函数可以限制,所有的代码块都可以限制其作用域(if/while/for/...) if (true) { let num = 100 console.log(num) // 100 } console.log(num) // 报错
// const 声明的变量,除了函数可以限制,所有的代码块都可以限制其作用域(if/while/for/...) if (true) { const num = 100 console.log(num) // 100 } console.log(num) // 报错
-
let
声明的变量的值可以改变,const
声明的变量的值不可以改变let num = 100 num = 200 console.log(num) // 200
const num = 100 num = 200 // 这里就会报错了,因为 const 声明的变量值不可以改变(我们也叫做常量)
-
let
声明的时候可以不赋值,const
声明的时候必须赋值let num num = 100 console.log(num) // 100
const num // 这里就会报错了,因为 const 声明的时候必须赋值
es6声明变量方法
- 六种
- var/function es5
- let/const es6
- import/class es6
箭头函数
-
简写匿名函数;
-
语法:
ary.forEach((k,i)=>{ log(); })
-
省略
-
形参只有一个可以省()
-
表达式只有一句可以省{},return;
-
易混:
(a,b)=>{a*b}//有返回值,但是省略 (a,b)=>a*b;//没有返回值
-
-
不同于匿名函数的点:
- 箭头函数没有arguments
-
关于this;
-
箭头函数失去原有的this;
-
与环境保持一致;
-
????????定时器环境不是在document下,this指向可以换成其他吗
- 箭头函数与普通函数的区别:
- 没有this
- 没有arguments
参数的默认值
-
原来的
-
新增的
//function(n=10){ n = n || 10 }
-
箭头函数
let fn = a=1 =>{ //默认为1;必须加小括号 //否则为undefined; }
解构赋值
- 定义:解构赋值,就是快速的从对象或者数组中取出成员的一个语法方式
-
解构对象
let obj = {name:"zhangsan",age:18} //原来: obj.name;obj.age; //解构: let {name} = obj;//定义一个变量,名字为name,这个变量可以获取后面obj的属性名值 let { name, age, gender } = obj //适用: log(name)//zhangsan log(age)//18; log(agender)//undefined;
obj必须是对象;没有的就是undefined;
-
结构数组;
//原有: let arr =[1,2]; //解构: let[num1,num2,num3] = arr; // log(num1)//1 log(num3)//undefined
-
区别:
- 解构数组[]
- 解构对象{}
- 不能混用
扩展简写
-
对象的创建
-
普通
-
解构
-
-
函数的简写;
obj合并对象方法
-
Object.assign(obj1,obj2);
-
返回值:obj1;
-
使用
模板字符串
- 反引号`` 搭配${}使用
- 保留换行
展开运算符
-
…
-
作用:
-
展开数组
-
展开对象
log(...[1,2,3]) //1,2,3; log(...{name:'zhang',age:18}) name:'zhang',age:18
类似去掉【】,{}
-
合并数组
let arr = [1, 2, 3, 4] let arr2 = [...arr, 5] console.log(arr2)//[1,2,3,4,5]
-
合并对象
let obj = { name: 'Jack', age: 18 } let obj2 = { ...obj, gender: '男' } console.log(obj2)//{name:'Jack,age:18,gender:'男'}
-
使用
~~~~js //数组方法: let arr =[1,2,3] Math.max(..arr)//由于max不能直接求数组中的最大值需要展开; //函数传参正着用:。。。在实参中 let arr = [1, 2, 3] function fn(a, b, c) { console.log(a) console.log(b) console.log(c) } fn(...arr) // 等价于 fn(1, 2, 3) function box(...arr){ console.log(arr) //[1,2,3,4,5,6] } box(1,2,3,4,5,6) ~~~~
-
-
倒着用(rest运算符,获取剩余参数)–。。。在形参中
//获取剩余参数 function box(...args){ //获取参数 log(arguments) } box(9,8,7) //原理: var ...args = 9,8,7; args == [9,8,7];
-
弥补箭头函数的缺点没有arguments;
模块化开发
- a, b 文件的引入顺序,关系到下方的文件能否使用上方文件的参数方法;
- 现状:a.js,b.js 之间无法相互引用,b.js需要使用a.js内部的代码
- 需求:js不介入.html文件 使用方法;
- 解决:模块化开发:
- CommonJS node.js中引入使用
- AMD 浏览器中引入使用
- 为了统一,es6 新增:
- import–导入-- 导入一模块内部的接口;
- export–导出-- 模块对外接口(函数/变量/对象)
- 定义:
- 一个js文件就是独立的模块(es6模块),这个模块内定义的所有变量外部无法使用;
- 需要使用只能通过export 导出后使用:
导出
- 法一:定义时导出
//c.js 中书写--以下是需要导出的变量/函数
export var a =1;
export function fn(){}
fn2(){}//未导出
- 法二:先定义再导出
//c.js
var b =2;
function fn3(){};
export{b,fn3};
- 默认导出
- 每个js文件可以有一个默认导出;
- 该默认导出,再其他文件被导入时,名字随意起
//定义模块
function foo() {
console.log('foo');
}
export default foo;
//默认导出的导入
import customName from './c.js
//customName是给导入的模块随意起了个名字
//from后边的是模块地址
导入
- 导入时与导出的变量名需要保持一致,否则报错
//c.js
import {fn,sum,a,b} from "c.js";
log(fn)//就可以正常使用了;
引入
最后,引入d.js即可/就不需要再引入c.js
- type=“moudle” //表明该文件有模块化处理
引入处理,否则会报错
//法一:
<script src="d.js" type="module"></script>
//法二:
<script type="module">
import {sum} from
</script>
新增数据类型Symbol
//1.
let s1 = Symbol();
let s2 = Symbol();
s1 ===s2 // false
//2.
let s1 = Symbol('a');
let s2 = Symbol('a');
s1 ===s2 // false
新增数据结构
- set/ map
- 原有的:ary(存有序数据) object(存键值对);
Set
- set 存储数据的解构,(数组升级版)
- 存储有序的数据,没有下标,数据不可重复;
- 使用:
- let s1 = new Set();
方法
- add
- 只能尾部添加
- 不能添加重复的
- delete
- 之呢个尾部删除
- has
- console.log(s1.has(‘1’))
- 判断set 中有无1 元素;
- forEach(()=>{})
- 只有k,没有index
去重
let arr2 =[1,2,3,3];
// 转为set结构且去重
let s2 = new Set(arr2);
// 转回数组
//法一:
let ar3 =[...s2];//利用 set可以展开的特点
log(ar3)
// 法二:
let ar4 = ar2.from(s2);
log(ar4)
//整合;
let ar5 =[...new Set(arr2)]
属性
- size
- console.log(s1.size)
Map
-
set 存储
- 类似对象,属性名可以是任何类型(包括函数)
-
原本的对象创建;function 作属性名,强制转为字符串
-
map 创建
- 法一:
- 法二:可以直接为数组形式;
es5新增Json
-
定义:特殊的字符串格式;
- js=》javascript
- o=》object
- n=》notation
-
语法:
let str1 ='{"name":"zhangsan","age":18}'; let str2 ='[{"name":"zhangsan","age":18},{"name":"zhangsan","age":18}]'
- 属性名:必须双引号;
- 属性值:可以是str,num,obj,ary,null,boolean ( 函数除外)
- jscon字符串 可以与对象 互相转化;
方法
-
JSON.parse
-
转为对象
-
转为数组
let obj1 = JSON.parse(str1) let ary1 = JSON.parse(str2)
-
-
JSON.stringfy
-
js对像转为js字符串;
JSON.strngfy(obj1);
-
场景
-
结合本地存储
-
需要将数组或者对像存入本地
-
只是铺垫:数组或对象需要先把数组或对像转为json字符串
-
使用时:读取本地json字符串,传为js对象;
-
-
达到:js对像或数组在浏览器中永久的存储(数据的持久化)
#### 案例–本地存储与JSON
1. 直接存obj 会失去内容setItem;
2. 使用JSON
正则表达式
-
创建:
let reg1 = /hello/; let reg2 = new RegExp('aeiou','i')
-
正则的方法:
test(); exec(); lastIndex;
-
搭配字符串方法:
replace() replaceAll(); match(); search();
-
正则表达式的构成;
-
字面量字符;
-
元字符;
-
-
元字符–特殊单字符:
. 除开换行符之外的任意一个字符; (只能出现在【】之外) \w (\W) 所有数字,大小写英文,下划线 \d (\D) 所有数字 \s (\S) 任意空白符(空格,tab键 /t,垂直制表符/v,换行符 \n(linux MacOS) \r(windows中两者))
-
元字符–空白符:
-
元字符–量词:
* 大于等于0个 + 大于等于1个 ? 0或1个 {m,} m个向上 {m} m个
-
元字符–范围:
| 或 [] 括号内部多选一 [a-z] 小写字母 [^...] 除开括号内任意一个
-
元字符–选择匹配符:
-
贪婪模式
{3,5} 此类结构会匹配3到5位字符;且会优先匹配上限也就是5 ;(该种匹配模式为贪婪模式);
使用非贪婪模式就在后方加上**?**
有个问题,非贪婪模式加上问号,不就和可选字符相同了嘛
- 正则表达式:
. 常与+ or*配合使用
一个表示字符类型一个限制字符的个数
只包含数字或字母的格式书写
常用:
什么开头什么结尾
限制只能出现几个的个数,而不是包含几个的个数:
分组的提取数据
[(.mp4)(.avi)(.wmv)(.rmvb)]$ 提取视屏格式的后缀为什么不行;
(.mp4|.avi|.wmv|.rmvb)$ 这为啥可以,.都没有转译 为啥能够获取?
动画库/网络地址存贮
- js动画库
- billbili.com/read/cv26644795/
- velocity.js
- swiper.js
- vanGreen (通过vue使用–开发小程序/网站) vant4
- boot CDN --存放网络地址
回调函数
- 将函数名直接做参数传递
- 功能:在一个函数内部使用某个函数内部的局部变量;
- 未传入的参数–返回值为undefined;
- fn && fn() ===> 如果为undefined 则出现短路运算;则调用函数
VELOCITY.JS的使用
-
引入js文件(cdn地址)
-
velocity 全局函数
- 语法:Velocity ( dom对象,{width: 200 , height : 200},{ duration:1000})
- 参数1 dom对象
- 参数2 动画最终效果
- 参数3 持续时间
let box = document . querySelector( ' #box' );
document.onclick = function () {
Velocity(box,
{ width: 200, height:200, opacity: 0.5 },
{duration: 10})
//第二栏:可以传递的参数:宽高内外边据border透明度; 逗号间隔
// 第三栏:可以传递的参数:可以是自己编写的函数(作为回调函数) 逗号间隔;
轮播图(直接切换版本)
-
transition
-
思路:
1. 所有的原点添加点击事件 (点击的按钮)并添加类名 - (遍历、排他) 2. 左右按钮 - 设置一个变量,记录该页的页码位置;(方便切换上一张或者下一张图片)currentPage - 小点的颜色跟随切换
面向对象
- 比如swiper;
- 简称 OOP
- js是一个面向对象的编程语言(但是前端框架里面目前不是纯面向对象–解决大多数问题都需要一个构造函数来解决问题)
- 趋势是函数是编程 =》如:vue react 小程序
特点
- 封装 – 核心的
- 封装构造函数(定义全局变量)-- 方法(定义一个函数)
- 继承
1. - 多态
面向过程
- 比如swiper中具体实现的细节;
对象的创建
-
字面量创建
let arr = [] let reg =// let obj ={name:'zhou'}
-
内置构造函数的创建 new 关键字;
let arr = new Array(); let reg2 = new RegExp(); let date = new Date(); let obj = new Object(); obj.name = 'jason',obj.age = 21;
目前object 属性名都是字符串类型 – 属性值可以实任何类型
let obj = {
name :'zhangsan',
"age" : 18,
run:function(){
console.log(obj.name +'name'+this);
//此处对象内部的方法中的this指向obj自己;
}
//es6 写法:
test(){
console.log('test');
}
//使用:
obj.age = obj.age+1;
obj.run();
obj.test();
}
- 工厂函数的创建
function createPerson(name,age,job)
{ var o = new Object();
o.name = name;
o.age = age;
o.job = job;
o.sayName = function()
{ alert(this.name); };
return o;
}
var person1 = createPerson('Nike',29,'teacher');
var person2 = createPerson('Arvin',20,'student');
- 使用构造函数 (也叫类 或 实例对象)的创建
function Person(name,age,job)
{ this.name = name;
this.age = age;
this.job = job;
this.sayName = function(){ alert(this.name); };
}
var person1 = new Person('Nike',29,'teacher');
var person2 = new Person('Arvin',20,'student');
- 原型创建对象
function Person(){}
Person.prototype.name = 'Nike';
Person.prototype.age = 20;
Person.prototype.jbo = 'teacher';
Person.prototype.sayName = function(){ alert(this.name);};
var person1 = new Person();person1.sayName();
- 添加对象的属性以及方法;
obj.sex = '男'
obj.sing = function (){
console.log(this.name)
}
- 遍历对象
in 与 of 都有当中的意思: of 强调所属关系(遍历元素本身);in强调所在关系(遍历属性名/键);
for ( let key in obj){
console.log()
}
for in / for of
- for in 遍历对象 ==> 返回键/属性名
- for of 遍历set map ==> 返回值;
this 的指向
-
构造函数内部:
- new 创建的对象; this==》 该对象;
-
对象方法内部;
- 谁调用this指向谁?
-
绑定事件
- 谁绑定指向谁;
-
全局中的–命名函数
- window
- 匿名函数内部传匿名函数 window
-
全局中的–匿名函数
- setTimeout ==> 指向 window
-
箭头函数
-
this没有自己的this
-
使用this==> 与上下文保持一致 大多数时候指向window
-
-
setTimeout 这里内部将 function 换成 箭头函数 ,此时setTimeout的this指向就从winow 换成了btn
-
改变this的指向
function fn(a,b){
console.log(this);
console.log(a);
console.log(b)
}
call
fn.call(参1[obj])
- 参数1 为一个对象,fn调用的时候fn的this被修改改为该对象;
fn.call()
- 参数2 为空 不修改;
- 多个参数
fn.call(obj,arg1,arg2) // 第一个为对象,后面作为函数的实参传入函数;
(原函数调用且受到影响)
apply
fn.call(参1[obj])
- 参数1 为一个对象,fn调用的时候fn的this被修改改为该对象;
fn.call()
- 参数为空 不修改;
- 最多就两个参数 第二个为数组数组里面一次传入函数;
fn.call(obj,arg1,arg2) // 第一个为对象,后面作为函数的实参传入函数;
(原函数调用且受到影响)
bind
let newFn =fn.bind(thisobj)
// 不会调用fn函数,返回一个新函数,新函数与fn函数公用一个函数题
// 此时调用新的函数this的值修改;原函数不会收到影响;
newFn(100,200);
箭头函数
立即执行函数
-
又名(自调用函数)
-
语法:
//1. (function(){})() //2. (function(){})
案例:面向对象–轮播
-
使用面向对象的功能去写
-
内部有一些属性,有一些方法
-
操作步骤(函数编程思想)
原代码的功能,写成一个函数,放到this上
- 直接封装(太散了,不易维护)
- let createSwiper(){}
- 全局变量全部放在开头
- 每一个大的部分,整理成一个功能;
- 将函数变成对象的属性;
- 全局变量前加this. ==>属性
- 封装的函数欠佳this. ==》方法
- 注意所有的方法内部的使用的全局变量,也要加上this.
- 对象的方法内部this指向dia调用它的对象,这里是
- 注意普通与箭头 的修改防止报错
- 所有整理的方法调用也要加上this;
- 经验:面向对象的时候,方法的内部使用箭头函数,使内外保持一致,防止报错
-
使用:引入js文件
-
补充:
-
加一个选择器;sel
-
原来是在document搜所元素,换为box
-
{autoplay:false} --》通过传入的参数将自动的播放设置是否自动播放;
- if(obj.autoplay == true){autoplay:false}
-
new MySwiper(‘.box’,{autoplay:true})
-
原型
-
每个构造函数都有一个原型(属性)prototype(显式原型),该属性指向原型对象 obj;
-
函数是对象,每次构造函数的创建对象都会创建空间,
-
函数名的比较 函数的内存地址 比较结果不同
-
浪费内存;
-
js内置的构造函数,使用原型(属性),避免了内存的浪费;
数组方法补充
-
ary1.push 实际上完整的写法是ary1.prototype.push;
构造函数内部自动做什么?
-
构造函数会自动创建一个this对象,自动返回this对象, 自动添加_ proto _
-
原型的概念;
-
原型+构造函数的创建方式
-
数组如何添加实例方法
原型的应用
- forEach的底层原理;unique 的原理
原型链
prototype 是函数对象独有的
_ proto _ 是所有对像都有的;
原型链的尽头:套娃,知道Object.prototype 原型为止;
es6 解决原型链==》类的添加(语法糖);
- 把函数封装好的叫语法糖;
类的写法
class Dog{
age=0;
constructor(name){
this.name =name;
}}
//这里的constructor 类似构造函数;
静态与实例
直接定义在构造函数上的方法和属性是静态的, 定义在构造函数的原型和实例上的方法和属性是非静态的
new Dog 自动执行 new时,constructor 自动执行;
类本身就是一个constructor 是函数而不是新增的户据方法;
实例熟悉/实例方法/constructor/静态的属性/方法
length;是实例方法,数组的方法大都是实例
静态
-
Array.form==>伪数组转为真数组;
-
Array.isArray==>判断是否是数组;
-
Date.now()
判断对象是不是后面的实例
ary instanceof Date
Object 是所有的对象的父类;
浅拷贝
原理
-
对象中的值获取到的是目的对象的地址值,
-
实际上克隆的对象与原对象共用一个孩子
let obj1 = { name:'zhangsan', age : 18, child:{ name:'zhangsanfeng' } } let obj2 ={ name: obj1.name; age: obj1.age; child: obj1.child; } //obj1 变量内的地址与obj2 变量里面存的地址值不同; //c创建obj1
实现
-
封装函数
function clone(obj){ let resOjb={} for( let key in obj){ let value = obj[key] 如果value 是一个对象 ,则直接把地址给了该对像 resObj[key] = value; } return resObj; }
for in 或 keys 遍历
-
展开运算符;
let newObj = {...obj};
-
assign方法
Object.assign({},obj); let newObj = Object.assign({},obj); //返回值,第一个对象;
-
第三方库 Lodash
//定义一堆方法,解决问题; _.clone(value) //bootCDN 网站引入该js文件
验证
- obj1 === obj2 false; obj1.child ==obj2.child true; ==> 浅拷贝;
深拷贝
- 孩子的孩子孩子的孩子可能多层嵌套都是对象;
实现
-
封装函数-递归( 报错,可能出现死递归,爆栈)
// 1. 判断value是对象则创建对象 // 2. typeof 判断值的类型 // 3. 属性hi是对象就调用函数拷贝+1; function deepCopy(obj) { // 参数obj为要拷贝的对象 // newObj为拷贝之后的新对象 let newObj = {} // 循环遍历要拷贝的对象,把要拷贝的对象的属性名和属性值都添加到newObj里面 for (let key in obj) { if (typeof obj[key] == 'object') { //如果要拷贝的属性值是一个对象就调用函数拷贝 newObj[key] = deepCopy(obj[key]); } else { newObj[key] = obj[key]; } } return newObj; }
//测试: let res4 = deepCopy(obj3) console.log(res4);
-
js自带函数(简洁,不用自定义函数) 循环引用;
-
思路:
- 把obj转为字符串再转回来;
- 字符串过来的
-
缺点:
- 不能拷贝函数(JSON字符串不能存储函数)
- 循环引用报错,
let obj2 = JSON.parse(Json.stringify(obj1)); //测试: obj2.child == obj1.child //false obj2 == obj1 ; // 循环报错; let zhangsan = {name : 'zhangsan'}; let zhangsanfeng = {name : 'zhangsanfeng'};
- JSON.stringify()
- JSON.parse()
-
第三方库
lodash
let newObj =_.cloneDeep(obj);
-
首选 json 需要函数其次考虑loadash ;
-
vue
-
vue响应式属性监听数据拦截
- 点击按钮:
-
http://cn.vuejs.cn
-
快速上手
<script> vue.createApp({ data(){ } }).mount('#app')//挂载 </script>
- 将vue文件放在网页中引入加载速度更快;
-
案例
//使用data中的数据,需要加上this; fn(){ this.age++ }
vue2 底层原理
- vlue 值
- writable是否可想而
- 是否遍历
- 是否
后期修改的属性值无法监听到,该缺点通过原型解决
vue3 底层原理
1. 创建代理对象,传入元对象;
let obj = {name : 'zhangsan ',age:19};
let proxyObj = new Proxy(obj,{
set(o,key,value){
console.log('设置/修改了对象的属性 就会执行')
}
console.log(o,key ,value )
})
// o是原对象,key是属性名,value是属性值;
// 后面修改obj的时候,就需要修改proxyObj;
proxyObj.age =999;
proxyObj.aa = 9999;
// 新增的属性也可以改;
XML
- 定义:可扩展标记语言,被设计为传输和存储数据。
- XML:类似HTML ,都是定义标签。
- HTML ,呈现数据,预定义标签;
- XML,存储与传输数据,自定义标签;
- ajax的应用现在使用json字符串替换来传输数据。xml是历史中的数据存储方式;
AJAX
- 基础原理:不刷新页面,通过HTTP协议够更新局部的页面内容
- 原生jQuery,fetch,axios
- 全称:asynic javascript
- 使用场景:注册页面,输入框提示,鼠标指定位置在加载(懒加载)提高加载效率
- 优点:
- 无需刷新页面与服务器端进行通信
- 可以根据用户时间来更新部分页面内容
- 缺点:
- 没有浏览历史,不可回退
- 存在跨域问题(同源)
- SEO不友好(网页内容,爬虫爬不了)
HTTP 协议
- 前后端交互的传输协议;
- hypertext transport protocol 协议,香医规定浏览器与万维网服务器之间相互通信 的规则
报文
-
请求报文
- 格式
-
请求行(Request Line)
- 请求方法:GET/POST
- 请求URL:请求路径和?参数等
- HTTP协议及版本:HTTP/1.1
-
请求头 (Header)
-
格式特点:==》名字 :空格 值
-
Host: atguigu.com
-
Cookie: name=guigu
-
Content-type: application/x-form-urlencoded
-
User-Aget: Chrome 83
application/x-form-urlencoded==> application/json ==> application/mul ==>
-
-
空行
-
请求体(Request Body)
- get 请求此处为空 post 请求为usernam=admin
- 参数
-
响应
- 格式
-
行 协议版本 状态码 OK
-
头
- Content-type: text/html;charst=utf-8(类型)
- Content-length:2048 (长度)
- Content-encoding: gzip (压缩方式)
- User-Aget: Chrome 83
-
空行
-
体
注:平常发送请求后,服务器传输回来的报文中,响应体中就是我们需要的内容;
报文的查看
- f12 ==》network ==》刷新 尚硅谷p6
- Headers
- General
- Response Headers (响应头)
- Request Headers (请求头)
- 展开是请求头
- 点击 view source 展开请求行
- Query String
- Perviews
常见状态码
-
五种状态
- 100~199;
- 一般我们看不到,因为表示请求继续
- 100: 继续请求,前面的一部分内容服务端已经接受到了,正在等待后续内容
- 101: 请求者已经准备切换协议,服务器页表示同意
- 200~299;
- 2 开头的都是表示成功,本次请求成功了,只不过不一样的状态码有不一样的含义(语义化)
- 200: 标准请求成功(一般表示服务端提供的是网页)**
- 201: 创建成功(一般是注册的时候,表示新用户信息已经添加到数据库)
- 203: 表示服务器已经成功处理了请求,但是返回的信息可能来自另一源
- 204: 服务端已经成功处理了请求,但是没有任何数据返回
- 300~399;
- 3 开头也是成功的一种,但是一般表示重定向
- 301: 永久重定向****
- 302: 临时重定向
- 304: 使用的是缓存的数据*******(get 请求默认都会被缓存)
- 305: 使用代理
- 400~499;
- 4 开头表示客户端出现错误了
- 400: 请求的语法服务端不认识
- 401: 未授权(你要登录的网站需要授权登录)
- 403: 服务器拒绝了你的请求****
- 404: 服务器找不到你请求的 URL*** **
- 407: 你的代理没有授权
- 408: 请求超时
- 410: 你请求的数据已经被服务端永久删除
- 500~599
- 5 开头的表示服务端出现了错误
- **500: 服务器内部错误 **
- 很可能是前端传输的数据错误
- 503: 服务器当前不可用(过载或者维护)
- 505: 请求的协议服务器不支持
- 100~199;
-
readystate
- 0,1,2,3,4
-
对比两者之间的特点
与服务器建立链接
- 保证客户端的接收和发送正常,服务端的接收和发送正常;
- 基于TCP/IP协议的三次握手
- 步骤:(三次握手)
- 客户端发送消息到服务器 =》服务端了解客户端想建立链接,客户端发信息正常
- 服务端回复信息 =》客户端了解服务端准备好了,服务端发信息正常
- 客户端回给服务器消息 =》服务端了解客户端准备好了
与服务器端来链接
- 基于TCP/IP的四次挥手
- 步骤
- 客户端发送我要断开的消息给服务器
- 服务端发送我已进入关闭等待状态给客户端
- 服务端再次发送这是最后一次发消息给你,当我再次接收到消息就会关闭
- 客户端发送给服务端消息,告诉服务器我已关闭,这是最后一体哦啊消息;
Express 安装
-
基于Node.js平台快速开发
-
报错:
npm : 无法加载文件 D:\Program Files\nodejs\node_global\npm.ps1,因为在此系统上禁止运行脚本。-CSDN博客
json-server 安装
-
vscode 右键根目录文件夹 终端打开
-
npm install json-server -g// 全局安装json-server
- bug
- nodejs 版本不需要最新,
- 安装位置放在c盘,新建两个文件夹装缓存,文件夹的权限全选
- 全局变量的配置,
- vscode 属性-安全-管理员打开
- bug
-
json-server -v //查看版本号
-
json-server .\text.json --watch
-
新建一个text文件,在里面用json格式写入内容;
-
使用上述代码监听
-
终端打开的位置与你所处的页面文件有关系;
==》cd C:\Users\木头同学\Desktop\123\ajax2-听课 切换所在位置
-
如在根目录下打开终端==》vscode正在page1.html==》输入某文件监控json文件代码
==》有==》打开 ==》没有==》在目前打开的文件位置新建一个json文件
-
-
打开窗口返回的http://localhost:3000 弹出页面
-
-
- 点击json文件中输入的/list0 或/list1 接口 或者输入 localhost:3000/list0 就到对应的接口获取到对应json数据
-
- 一级的key键名,代表接口的数量
- 访问localhost 不可以关闭 终端,否则访问失败
- 重新进入 : 打开终端 + json-server .\text.json --watch 即可
-
请求方式
-
每一个 HTTP 请求在请求行里面会有一个东西叫做请求方式
-
主要看接口文档使用的类型,决定具体使用的请求类型
-
不同的请求方式代表的含义不同
-
GET: 一般用于获取一些信息使用(获取列表)
-
POST: 一般用于发送一些数据给服务端(登录)
-
PUT: 一般用于发送一些数据给服务当让其添加新数据(全体更新)
-
PATCH: 是和 PUT 方式类似的一个方式,一般用于更新局部数据(更新密码)
-
DELETE: 一般用于删除某些数据
-
OPTIONS: 允许客户端查看服务端性能
-
HEAD: 类似于 GET 的请求,只不过一般没有响应的具体内容,用于获取报文头
-
CONNECT: HTTP/1.1 中预留的方式,一般用于管道链接改变为代理的时候使用
-
// get 请求
myget.onclick=function(){
let xhr =new XMLHttpRequest();
xhr.open("GET","http://localhost:3000/list0");
xhr.onload=function(){
if(xhr.status ===200){
console.log(JSON.parse(xhr.responseText));
}
}
xhr.send();
}
// post 请求
mypost.onclick=function(){
let xhr = new XMLHttpRequest();
let url = "http://localhost:3000/list0/1"
// url + 协议+域名+端口+接口+id号
xhr.open("POST",url);
xhr.onload=function(){
if(/^2\d/.test(xhr.status)){
console.log(JSON.parse(xhr.responseText));
}
}
// 不一样的模块:提交的内容需要额外添加上固定格式字符串;
// - 表单字符串 name=kerwein&age=100
// - json字符串 {"name":"kerwin"}
// 为了辨别字符串格式send语句前添加方法
// 01 表单字符串
// xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded")//表单form字符串格式
// xhr.send('uName=hanmeimei&uAge=111');//向url中的对应接口插入对应的内容;
// 02 json字符串
xhr.setRequestHeader("Content-Type","application/json");
xhr.send(JSON.stringify(
{
uName:'xiaokeai'
}
))
// 03 服务器问题
// live-server 与 json-server 冲突,live-server 自动刷新,因此控制台看不见post请求的传输数据;
// 04 解决
// 更换server 为preview on webserver 点击底部Port:5500禁止掉 占用8080端口
// 但可以成功添加项目,但控制台依旧没有输出的原因,在network查看可知status 为201,因此修改状态码;
// 01 put 请求 url后面都需要加上接口名和id号
// 有xhr.setRequestHeader
// 新的传入对象会覆盖掉原有接口中的所有键值对
// 如:{uNew:'xiaoming'} ==替换掉==》{uOld:'daming',uAge:15}
// 02 patch 请求
// 有xhr.setRequestHeader
// 新传入的对象只会修改原有的键名,剩余的会自动保留
// 03 delete 删除 url 后面加接口名和id号;send为空即可
// 无xhr.setRequestHeader
// 04 get
// 默认获取所有的接口键值对;因此根据键某个接口中的值获取的方法,直接卸载url中
// xhr.open("GET","http://localhost:3000/list0?uName=xiaokeai")
// ?开头 &与 返回数组
nodejs的使用
- nodejs是js的运行环境 (chrome=>v8;本质将js引擎安装到用户电脑上,js可脱离浏览器运行)
- js原来使用前端,nodejs可以做后端
- 国内主要功能使用nodejs辅助前端开发,国外使用它做后端;
- nodejs基础api;
- nodejs框架;
- 掌握:
- 安装nodejs
- 长期稳定版Lts
- previous – 工作中常用老版,可能使用10开始的版本;
- 默认c盘,关系到环境变量适配,安装后,可重启vscode;
- 验证:
- 终端中验证;
- vscode中 终端中打开node -v
- cd… 后退一层
- cd xx 进入某层
- node 文件名 执行某个文件
- 必须保证进入父文件夹的条件下;
- 终端中验证;
- npmjs.com语言基础使用
- 了解nodejs api,模块化开发,nodejs,基础介绍;
- 安装nodejs
防抖和节流
定义:
-
防抖:短时间内触发多次,重新计时,在ns后执行该事件;
-
节流:ns 内重复触发,规律的执行。从一开始就定时多久就开始触发;
- 故事理解:
- 防抖:一段时间内上电梯,源源不断有人上来,每一次都重新几时,等待最后一个15s后运行;
- 节流:第一个人上电梯,15s准时运行一次;和设置时间周期相关联,与点击次数关联不大,不要理解成点击几次x按照周期执行几次。
作用:
-
降低回调执行频率,节省计算资源;
-
应用场景:
- 搜索框,input框内容的输入;
- 窗口大小resize,调整,防止重复渲染;
- 页面内容滚动加载;
原理:
// 防抖:
// 连续触发,1s后执行,此段时间中触发的都会清楚上次延时器;
<input type="text">
// step0 ;
let ipt = document.querySelector("input");
let timer = null;
// step1;
ipt.oninput = function (){
// step2; timer=null
// step4; 不断触发,timer=1,2,3,4, ==》不断请理延时器;
if(timer){
clearTimeout(timer)
};
// step3 timer!=0
// step5 timer数值不断更新,由于timer不断更新,但内部changeIpt需要延时1s执行,changeIpt未被调用
timer = setTimeout((e)=>{changeIpt()},1000) // timer返回值是整数;
}
changeIpt function(){
log('检测ipt中的文本');
}
// 节流
// 0. 通常有两种解决方案
// 1. 时间戳写法
function throttled1(fn, delay = 500) {
let oldtime = Date.now()
return function (...args) {
let newtime = Date.now()
if (newtime - oldtime >= delay) {
fn.apply(null, args)
oldtime = Date.now()
}
}
}
// 2. 定时器写法
let timer = null;
ipt.oninput = function(){
// step1
if(timer==null){
// step2 执行延时器,timer值修改不为null,timer延时+规定1s内部的一直未执行;
// step3 规定时间内null除第一次一直timer不为0,不调用函数,直到一轮规定时间到了,timer被设置为null,继续下一次调用
timer = setTimeout(()=>{
changeIpt()
timer = null
},1000)
}
}
jsonp
-
常见于搜索引擎
-
用法:
- 利用script标签与src属性中放入回调函数,传递参数,天然支持跨域这种能力
- 可跨域访问文档,js脚本,不可访问图片视频
- 只支持get请求;
-
案例:
毒霸网址大全 百度的接口,f4 => 网络 => js筛选 ==》搜索栏中输入b==>网络出现=》script标签 ==》
Day1305
Promise
-
用法:解决回调地狱问题,减少嵌套保证异步操作的顺序;
-
原理:promise 本质是一个状态机,构造函数,对象里面有一个属性,记录了异步操作的状态;
-
语法:
/** 01 - 使用Promise构造函数,创建promise实例。 这个构造函数需要一个参数函数, 这个参数函数中写一个异步操作, 在这个异步操作成功以后,调用resolve; 在这个异步操作失败后 , 调用reject; **/ // 02 - 得出异步操作的状态 ==》{ 进行中 ,成功 ,失败 } let p = new Promise(function(resolve,reject){ //异步操作: //在这个异步操作成功以后,调用resolve //在这个异步操作失败以后,调用reject }); // 03 - 异步下一部分操作; // 03.1 then 用法一: p.then(function(){},function(){}) // function 第一个,在promise 对象异步操作成功以后执行; // function 第二个,在promise 对象异步操作失败以后执行; // 避免将then中的操作套用在p中的function 内部; // 03.2 then 用法二: p.then(function(){ // 会在promise 对象内部的异步操作成功之后执行; }) p.catch(function(){ // 会在promise 对象内部的异步操作失败以后执行; }) // 03.3 then 用法三: p.then(function(){}).catch(function(){})
axios基本使用
Params /Data
-
params 》搜索参数》get使用;
-
data 》请求体》post 使用,配合请求体转换的类型headers;
设置方法1:
axios({请求的配置对象}) 返回一个promise对象
axios({}).then(r=>{ r不是服务器返回的数据,r.data 是服务器返回的数据 }).catch()
let p = axios({})
p.then().catch()
设置方法2:
axios.get(url,{params:{title:'1'}}).then().catch()
axios.post(url,请求体对象)
axios.post(url,{title:'aa'})
axios.put(url,请求体对象)
axios.patch(url,请求体对象)
axios.put(url,{title:'aa'})
axios.patch(url,{title:'aa'})
axios.delete(url)
设置方法3:
// 01. 创建一个对象
let http = axios.create({
baseURL:''
headers:{'content-type':''}
})
使用http对象时候,会自动使用上面已经配置好的 信息
http.get(url,{params:{title:'1'}}).then().catch()
http.post(url,请求体对象)
http.post(url,{title:'aa'})
http.put(url,请求体对象)
http.patch(url,请求体对象)
http.put(url,{title:'aa'})
http.patch(url,{title:'aa'})
http.delete(url)
基本步骤
1. 引入案axios
2. 引入参数;
3. 设置参数:
-- axios({}).then(r=>{}).catch(err=>{});
4. 设置方法2:
-- async function fn(){
let r= await axios({
})
}
r不是服务器返回的数据,服务器返回的数据是r.data
axios综合案例
-
思路
1. js代码; 2. 准备详情文件夹:login,register,index.detail.html, axios.js; 代码 3. 打开server; 4. 接口服务器的基准地址设置; 5. 服务器是否起开cors; 6. 引入axios 与request; 7. 模块化开发; 8. ?id=1 详情页,不能直接使用liveserver打开,需要从列表页直接跳转; 9. location.search = 1; 10. URLSearchParams(location.search.slice); 11. 关于function 定义完成之后,调用报错, xx is not defined; - 单词拼写错误 - function 不是全局函数,不在调用的范围内 - 容易忽略的,script type = "module" 该模块化封装的函数是局部的;外部用不了; - 行内事件要求的方法是全局函数; - 修改办法: window.myFun(){} 直接添加到window属性上; 12. localstorage将登录后的个人信息存入本地,随用随取; - 我的思路,uid,直接从http获取的地方取出,根据实际使用暂时 12. 难点:记忆axios的使用方法,传参方式;
-
注册
<body> <div> 用户名:<input type="text"> <br> 密码:<input type="text"> <br> 重复密码:<input type="text"> <br> 昵称:<input type="text"> <br> <button id="register"> 注册 </button> </div> <!-- 01-1 基础的script的引入 --> <!-- <script src="./js/axios.js"></script> <script src="./js/request.js"> </script> --> <!-- 01-2 模块化开发,配合http的引入办法 --> <script type="module"> import http from './js/request2.js'; // http.get(); // console.log(http.get()); const regAPI = users/register; let ipts = document.querySelectorAll('input'); register.onclick=function(){ let username=ipts[0].value; let password=ipts[1].value; let rpassword=ipts[2].value; let nickname=ipts[3].value; <!---02-1 基础用法,get.then.catch--> http.post( regAPI, {username,password,rpassword,nickname:nickname} ).then(r=>{ console.log(r.data); }) } <!---02-2 修改用法,async,await--> </script> </body>
-
登录
-
主页
1. 引入文件; 2. 定义listAPI,发送请求; 3. 参数的定义; 4. 通过a + id跳转到详情页;(不能通过liveServer进入) 5. 获取搜索参数;
-
详情页
1.
-
购物车页
- 修改一条商品状态函数
// 疑惑: 1. 为什么这里传递参数需要使用params; 2. dan'tiao
1. 不熟练的知识点:
location 获取参数,包括哪些;
href;
host;
port;
search;
hash;
new URLSearchParams()// 传入一个搜索字符串;得到对象
https://juejin.cn/post/7238999952553820218//
cookie
基础知识
- 辨别用户身份,进行session跟踪存储在用户本地终端,以文本形式存在;
- 目的:就算没有登录,也能够识别用户的身份;
- 国内:国内请求会自动随着http协议的发送,直接将cookie连接;
- cookie 只有使用http协议打开就会直接生成,比如open witth liveserver
- 读取有域名限制,意思:百度,淘宝各自使用自己的cookie
- cookie 具有时效性;并非永久存储 最多十年左右;
- expires;
- max-age;
- 存储形式:
- cookie 以字符串的形式存储数据的位置;
- 每一个http请求都会在请求头中携带cookie到服务器端;
- 每一个http相应都会在响应头中携带cookie到客户端;
- cookie,不需要手动设置,会在客户端和服务端之间游走的数据;
- 我们需要设置一下cookie的内容
- 小:4kb最大;
cookie攻击
- xss 在网站插入脚本, 在网站运行,获取到用户身份,来模拟用户的登录;
- csrf 在网站插入非法连接,自动
- 攻击者诱导受害者进入第三方网站,第三方网站中,向被攻击网站发送跨站请求,利用受害者在被攻击网站已经获取的注册凭证,绕过后台的用户验证,达到冒充用户对被攻击的网站执行某项操作的目的
- csrf 典型的攻击流程
- 受害者登录a.com,并保留了登录凭证cookie;
- 攻击者引诱受害者b.com;
- b.com 向a.com发送请求:a.com/act=xx;浏览器默认携带a.com的cookie;
- a.com接收到请求,对请求进行验证,并确认是受害者的凭证,误以为是受害者自己发送的请求;
- a.com以受害者的名义执行了act=xx;
- 攻击完成,攻击者在受害者不知情的情况下,冒充受害者,让a.com执行自己定义的操作;
- 因此:
- 微信/qq当中无法打开某些连接,需要复制粘贴到浏览器;
- 将登录信息存入到localStorage中,localStorage不会随着http请求发送,而cookie会
cookie操作;
-
添加cookie设置cookie;
-
读取;
-
修改,再次设置;
-
删除;
// 添加,设置 document.cookie ='username=zhangsan' // 读取: document.cookie; // cookie 时效的设置 // 删除==>原理:把过期时间设置为过去的
每一次添加不会覆盖而是拼接;
一次读取所有的cookie,每一个键值对用分号连接;分号空格连接起来;
cookie 的时效: (过期时间)
默认:会话:浏览器关闭就没有
-
属性:
- cookie时效;
- expires;
- path: 路径;
- 通常自动把当前页面的路径设置上;
- 一半将路径统一设置为 / 根路径
- domain 域名;
cookie 第三方库;
-
js-cookie ;针对性设置
// 存 Cookies.set('d',2); Cookies.set('e','2',{expires:365}) // 修改 Cookies.set('d','3') // 读取 Cookies.get('d'); // 删除 Cookies.remove('e');
感悟:许多比较繁杂机械的工序是可以通过封装第三方库简化的,我能不能找到一些比较常用且繁杂的方法来封装自己的工具一次来达到获利的效果呢?
中国的应用层面很厉害,但是系统中使用的很多是国外封装好的代码.
因此,国外如俄罗斯,乌克兰,许多从小学开始学编程; 底层封装的代码,是现在所缺少的;
同源策略
- 浏览器中有的安全策略,叫做同源策略;
- a.com 页面,发起的ajax请求,只能请求a.com 开头的接口
- 页面的网址和接口的地址要一样
- 协议,域名,端口号,三者一致
- https://a.com
- http://a.com
- 不同源,协议不同
- https://a.com:80
- https://a.com:8080
- 不同源,端口号不同
- 衍生的问题:搜索窗口,有跨域的需求;
跨域解决
-
jsonp (较少)
-
cors (较多)
- 服务器配置响应头,access-control-allow-orign,
- 允许访问的地址
-
代理服务器
- nginx代理服务器 (较多)
- 开发中使用代理插件,但是项目上线不能使用;
- 开发环境==> 本地开发==> liverserver 测试页面
- 线上环境==> 写好的前端代码,放到公司租用的服务器上;
-
websocket
跨域jsonp
-
百度搜索引擎的应用:
缺点:只能发起get请求,不能上传图片,视频等比较大的内容;
jsonp:利用src 属性,天然支持跨域能力(重点),不受同源策略的影响.
<!-- 1. 难点:如何 查询js访问的api, 目前是使用毒霸的api接口;谷歌?等 --> <!-- 思路: 1. ipt的value值, 2. 创建script标签元素; 3. 修改script标签的src值; 4. 插入元素; 5. 审查网络元素;可以加载js文件 6. 关键内容,查看响应,了解,我们所需要的参数; 7. 遍历显示所需要的参数到页面; --> <body> <input type="text" id="ipt"> <ul id="list"> <li></li> </ul> <script> function loadlist(res){ console.log(res); let str = ''; res.s.forEach((v,i)=>{ str += ` <li> ${v} </li> ` }); console.log(str); list.innerHTML = str; } ipt.oninput = function(){ let word = document.querySelector('#ipt').value; console.log(word); let url=`https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=${word}&_=${Date.now()}&cb=loadlist`; let sc = document.createElement('script'); sc.src = url; document.body.appendChild(sc); } </script> </body>
跨域判断
跨域-代理服务器-nginx
- nginx: 反向代理服务器; 需要自己配置服务器,后端;
- 跨域存在与浏览器和服务器之间;
- 跨域存在于浏览器和服务器之间
- 但是服务器和服务器之间是没有跨域问题;
- 代理插件 ==> react 学习,但是项目线上不能够使用;
- 线上环境, ==> 代理
websocket
-
双向通信技术 ==>微信聊天,急事通信;
-
需要服务器支持;
-
websoket api 如何使用:
// 接收消息 let ws = new WebSoket('ws://xxx.com';) ws.onopen = function (){ log('连接已经打开'); }; ws.onclose = function(){ log('连接 关闭'); } ws.onerror = function (){ log('连接出错'); } ws.onmessage = function(evt){ log('接收到消息'); log(evt.data); } // 发送消息,字符串,json字符串格式; ws.send(JSON.stringify({msg:'aaa',id:11,coiceUrl:'aaa'}))
-
注册文心一言,讯飞星火大模型; 免费有限制,一天几百次;
- socken
ata);
})
}
- socken
-
-
登录
-
主页
1. 引入文件; 2. 定义listAPI,发送请求; 3. 参数的定义; 4. 通过a + id跳转到详情页;(不能通过liveServer进入) 5. 获取搜索参数;
-
详情页
1.
-
购物车页
- 修改一条商品状态函数
// 疑惑: 1. 为什么这里传递参数需要使用params; 2. dan'tiao
1. 不熟练的知识点:
location 获取参数,包括哪些;
href;
host;
port;
search;
hash;
new URLSearchParams()// 传入一个搜索字符串;得到对象
https://juejin.cn/post/7238999952553820218//
cookie
基础知识
- 辨别用户身份,进行session跟踪存储在用户本地终端,以文本形式存在;
- 目的:就算没有登录,也能够识别用户的身份;
- 国内:国内请求会自动随着http协议的发送,直接将cookie连接;
- cookie 只有使用http协议打开就会直接生成,比如open witth liveserver
- 读取有域名限制,意思:百度,淘宝各自使用自己的cookie
- cookie 具有时效性;并非永久存储 最多十年左右;
- expires;
- max-age;
- 存储形式:
- cookie 以字符串的形式存储数据的位置;
- 每一个http请求都会在请求头中携带cookie到服务器端;
- 每一个http相应都会在响应头中携带cookie到客户端;
- cookie,不需要手动设置,会在客户端和服务端之间游走的数据;
- 我们需要设置一下cookie的内容
- 小:4kb最大;
cookie攻击
- xss 在网站插入脚本, 在网站运行,获取到用户身份,来模拟用户的登录;
- csrf 在网站插入非法连接,自动
- 攻击者诱导受害者进入第三方网站,第三方网站中,向被攻击网站发送跨站请求,利用受害者在被攻击网站已经获取的注册凭证,绕过后台的用户验证,达到冒充用户对被攻击的网站执行某项操作的目的
- csrf 典型的攻击流程
- 受害者登录a.com,并保留了登录凭证cookie;
- 攻击者引诱受害者b.com;
- b.com 向a.com发送请求:a.com/act=xx;浏览器默认携带a.com的cookie;
- a.com接收到请求,对请求进行验证,并确认是受害者的凭证,误以为是受害者自己发送的请求;
- a.com以受害者的名义执行了act=xx;
- 攻击完成,攻击者在受害者不知情的情况下,冒充受害者,让a.com执行自己定义的操作;
- 因此:
- 微信/qq当中无法打开某些连接,需要复制粘贴到浏览器;
- 将登录信息存入到localStorage中,localStorage不会随着http请求发送,而cookie会
cookie操作;
-
添加cookie设置cookie;
-
读取;
-
修改,再次设置;
-
删除;
// 添加,设置 document.cookie ='username=zhangsan' // 读取: document.cookie; // cookie 时效的设置 // 删除==>原理:把过期时间设置为过去的
每一次添加不会覆盖而是拼接;
一次读取所有的cookie,每一个键值对用分号连接;分号空格连接起来;
cookie 的时效: (过期时间)
默认:会话:浏览器关闭就没有
-
属性:
- cookie时效;
- expires;
- path: 路径;
- 通常自动把当前页面的路径设置上;
- 一半将路径统一设置为 / 根路径
- domain 域名;
cookie 第三方库;
-
js-cookie ;针对性设置
// 存 Cookies.set('d',2); Cookies.set('e','2',{expires:365}) // 修改 Cookies.set('d','3') // 读取 Cookies.get('d'); // 删除 Cookies.remove('e');
感悟:许多比较繁杂机械的工序是可以通过封装第三方库简化的,我能不能找到一些比较常用且繁杂的方法来封装自己的工具一次来达到获利的效果呢?
中国的应用层面很厉害,但是系统中使用的很多是国外封装好的代码.
因此,国外如俄罗斯,乌克兰,许多从小学开始学编程; 底层封装的代码,是现在所缺少的;
同源策略
- 浏览器中有的安全策略,叫做同源策略;
- a.com 页面,发起的ajax请求,只能请求a.com 开头的接口
- 页面的网址和接口的地址要一样
- 协议,域名,端口号,三者一致
- https://a.com
- http://a.com
- 不同源,协议不同
- https://a.com:80
- https://a.com:8080
- 不同源,端口号不同
- 衍生的问题:搜索窗口,有跨域的需求;
跨域解决
-
jsonp (较少)
-
cors (较多)
- 服务器配置响应头,access-control-allow-orign,
- 允许访问的地址
-
代理服务器
- nginx代理服务器 (较多)
- 开发中使用代理插件,但是项目上线不能使用;
- 开发环境==> 本地开发==> liverserver 测试页面
- 线上环境==> 写好的前端代码,放到公司租用的服务器上;
-
websocket
跨域jsonp
-
百度搜索引擎的应用:
缺点:只能发起get请求,不能上传图片,视频等比较大的内容;
jsonp:利用src 属性,天然支持跨域能力(重点),不受同源策略的影响.
<!-- 1. 难点:如何 查询js访问的api, 目前是使用毒霸的api接口;谷歌?等 --> <!-- 思路: 1. ipt的value值, 2. 创建script标签元素; 3. 修改script标签的src值; 4. 插入元素; 5. 审查网络元素;可以加载js文件 6. 关键内容,查看响应,了解,我们所需要的参数; 7. 遍历显示所需要的参数到页面; --> <body> <input type="text" id="ipt"> <ul id="list"> <li></li> </ul> <script> function loadlist(res){ console.log(res); let str = ''; res.s.forEach((v,i)=>{ str += ` <li> ${v} </li> ` }); console.log(str); list.innerHTML = str; } ipt.oninput = function(){ let word = document.querySelector('#ipt').value; console.log(word); let url=`https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=${word}&_=${Date.now()}&cb=loadlist`; let sc = document.createElement('script'); sc.src = url; document.body.appendChild(sc); } </script> </body>
跨域判断
跨域-代理服务器-nginx
- nginx: 反向代理服务器; 需要自己配置服务器,后端;
- 跨域存在与浏览器和服务器之间;
- 跨域存在于浏览器和服务器之间
- 但是服务器和服务器之间是没有跨域问题;
- 代理插件 ==> react 学习,但是项目线上不能够使用;
- 线上环境, ==> 代理
websocket
-
双向通信技术 ==>微信聊天,急事通信;
-
需要服务器支持;
-
websoket api 如何使用:
// 接收消息 let ws = new WebSoket('ws://xxx.com';) ws.onopen = function (){ log('连接已经打开'); }; ws.onclose = function(){ log('连接 关闭'); } ws.onerror = function (){ log('连接出错'); } ws.onmessage = function(evt){ log('接收到消息'); log(evt.data); } // 发送消息,字符串,json字符串格式; ws.send(JSON.stringify({msg:'aaa',id:11,coiceUrl:'aaa'}))
-
注册文心一言,讯飞星火大模型; 免费有限制,一天几百次;
- socken
-