From f8913c9c72c830c6eaa8c6c112a22f4186c085d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A8=8B=E8=88=9C?= <1991510644@qq.com> Date: Fri, 29 Dec 2023 10:04:04 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BD=9C=E4=B8=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "51 \347\250\213\350\210\234/20231108.md" | 261 +++ "51 \347\250\213\350\210\234/20231128.md" | 201 ++ "51 \347\250\213\350\210\234/20231213.md" | 142 ++ "51 \347\250\213\350\210\234/20231214.md" | 2433 +++++++++++++++++++++ 4 files changed, 3037 insertions(+) create mode 100644 "51 \347\250\213\350\210\234/20231108.md" create mode 100644 "51 \347\250\213\350\210\234/20231128.md" create mode 100644 "51 \347\250\213\350\210\234/20231213.md" create mode 100644 "51 \347\250\213\350\210\234/20231214.md" diff --git "a/51 \347\250\213\350\210\234/20231108.md" "b/51 \347\250\213\350\210\234/20231108.md" new file mode 100644 index 0000000..7e2d9ae --- /dev/null +++ "b/51 \347\250\213\350\210\234/20231108.md" @@ -0,0 +1,261 @@ +### 表单复习 + +1. **获取或修改表单里的值**:表单对象 . value = 值 +2. **设置表单类型**:表单对象 . type = 'password' +3. **单选框,复选框**,选中与不选中:表单对象 . checked= true 或 false +4. **按钮的可用与不可用**:表单对象 . disabled = true 或 false +5. **下拉框的选择**:表单对象 . selected = true 或 false + +### 自定义属性 + +标准属性: 标签天生自带的属性 比如class id title等, 可以直接使用点语法操作比如: disabled、checked、selected + +自定义属性: + +- 在html5中推出来了专门的data-自定义属性 + + +- 在标签上一律以data-开头 + + +- 在DOM对象上一律以dataset对象方式获取 + +~~~ html + +
自定义属性
+ + +~~~ + +### 间隔函数(定时器函数) + +~~~ html + +~~~ + +### 作业 + +用户注册倒计时 + +~~~ html + + +
+ + + +~~~ + +顺序轮播图 + +~~~ html + + + + + + + + 轮播图点击切换 + + + + +
+
+ +
+ +
+ + + + +~~~ \ No newline at end of file diff --git "a/51 \347\250\213\350\210\234/20231128.md" "b/51 \347\250\213\350\210\234/20231128.md" new file mode 100644 index 0000000..4b92998 --- /dev/null +++ "b/51 \347\250\213\350\210\234/20231128.md" @@ -0,0 +1,201 @@ +## 概念 + +**正则表达式**是用于匹配字符串中字符组合的模式。在 JavaScript中,正则表达式也是对象。这些模式被用于 RegExp 的 exec 和 test 方法, 以及 String 的 match、matchAll、replace、search 和 split 方法。 + +## 创建正则表达式 + +两种方法:[字面量](https://so.csdn.net/so/search?q=字面量&spm=1001.2101.3001.7020)方式、构造函数方式 + +```js +//字面量方式,其由包含在斜杠之间的模式组成,如下所示: +var re = /ab+c/; +//构造函数方式,调用RegExp对象的构造函数,如下所示: +var re = new RegExp("ab+c"); +``` + +## 正则表达式常用方法 + +- 校验数据 + +### test(字符串) + +测试字符是否满足正则表达式规则,如果测试到有,则返回true;没有则返回flase +语法:正则表达式.test(字符串) 正则表达式提供的方法 + +```js +var reg=/[123]/ +var str='1' +var result=reg.test(str) +console.log(result)//flase +``` + +### search(正则表达式) + +search() 方法执行正则表达式和 String 对象之间的一个搜索匹配。 +语法:字符串.search(正则表达式) 字符串提供的方法 + +```js +var reg=/\d/ //匹配阿拉伯数字 +var str="abcdefg3sgbh" +var res=str.search(reg) +console.log(res) //7 +//验证方法 找到返回下标 找不到返回-1 +//在字符串中找到满足正则表达式的那一部分 +``` + +区别: +.test()方法是正则表达式提供的,.search()是字符串提高的, +.test()方法返回布尔值,search()返回下标 + +- 提取数据 + +### 正则表达式.exec(字符串) + +exec() 方法在一个指定字符串中执行一个搜索匹配。返回一个结果数组或 null。 正则表达式提供的方法 + +```js +var reg=/\d/ +var str="abcd456efg" +var res=reg.exec(str) +console.log(res)//返回一个数组,内容是4 +//字符串中满足正则表达式的部分提取出来 +//遇到满足条件的就返回,所以只返回4 +``` + +区别: +正则表达式.exec(字符串),正则表达式提供的方法 +字符串.match(正则表达式) 字符串的方法 +相同: +都返回一个数组,只要匹配到符合规则的数据就返回 + +- 替换数据 + +### 字符串.replace(正则表达式,新的内容) + +replace() 方法返回一个由替换值(replacement)替换部分或所有的模式(pattern)匹配项后的新字符串。模式可以是一个字符串或者一个正则表达式,替换值可以是一个字符串或者一个每次匹配都要调用的回调函数。如果pattern是字符串,则仅替换第一个匹配项。字符串提供的方法 + +```js +var reg=/\d/ +var str="11123bcd" +var res=str.replace(reg,"a") //将数字换为a +console.log(res)//a1123bcd 只要匹配到符合规则的就返回 +``` + +## 范围类 + +在[]组成的类内部是可以连写的 + +```js +let text = 'a1B2d3X4Z5' +let reg=/[a-zA-Z]/ +text.replace(reg,'Q')//Q1Q3Q4Q5 +``` + +## 字符类取反 + +很多时候碰到这么一种情况,即不想匹配某些字符,其他都匹配。此时,可以使用字符类取反——使用元字符^,创建反向类,即不属于某类的内容。 + +[^abc]表示不是字符a或b或c的内容 + +```js +let reg=/[^abc]/g +let text='a1b2c3d4e5' +console.log(text.replace(reg,'X')) //输出aXbXcXdXeX +``` + +## 修饰符 + +在正常情况下,正则匹配到第一个匹配项则停止,并且默认大小写敏感,如果想修改默认选项,则需要修饰符。 + +### g:global全文搜索 + +```js +var reg=new RegExp('l'); +var a='hello'.replace(reg,'f') +console.log(a)//输出结果为:heflo + +var reg=new RegExp('l','g');//加上g标签表示全文搜索 +var a='hello'.replace(reg,'f') +console.log(a)//输出结果为:heffo (所有的 l 都换成了 f ) +``` + +### m:multiple lines 多行搜索 + +```js +var reg=new RegExp('od') +var str='so good\n so good' +var result=str.replace(reg,'hi') +console.log(result) +//结果为: +so gohi +so good +//只给第一行匹配了 + +var reg=new RegExp('od','gm')//加上m标签表示多行匹配 +var str='so good\n so good' +var result=str.replace(reg,'hi') +console.log(result) +//结果为: +so gohi +so gohi +``` + +### 其他标志符 + +s:允许 . 匹配换行符。 +u:使用unicode码的模式进行匹配。 +y:执行“粘性(sticky)”搜索,匹配从目标字符串的当前位置开始。 + +## 量词符 + +### 贪婪模式 + +之前说了正则表达式的量词,但量词会带来一个到底匹配哪个的问题 +例如: + +```js +var str="12345678" +var reg=/\d{3,6}/g +str.replace(reg,'X') //X78 +``` + +可以看到结果是将123456 六个数字替换成了X,所以我们可以得到,正常模式下,正则表达式会尽可能多的匹配。正常情况下,正则表达式采用贪婪模式,即,尽可能多的匹配。 + +### 非贪婪模式 + +一但成功匹配不再继续尝试,这就是非贪婪模式。 +只需要在量词后加上?即可 + +```js +var str="12345678" +var reg=/\d{3,6}?/g +str.replace(reg,'X') //X45678 +``` + +## 分组 + +在使用正则表达式的时候会想要匹配一串字符串连续出现多次的情况,使用()可以达到分组的功能 +例如:`(hello){3}` +使用符号 | (或)实现选择的功能 +例如: + +```js +var str='12341235' +let reg=/123(4|5)/g +//1234 1235二选一 +``` + +## 反向引用 + +将一种格式的时间字符串:yyyy-MM-DD转为MM/DD/yyyy类型格式字符串。 +由于年月日是不固定的,没法直接转换为固定数值。这时我们可以使用反向引用解决这个问题。 +利用$n,n代表着分组的序号,序号是从1开始的。 + +例如: + +```js +let text='2022-02-23' +let reg=/(\d{4})-(\d{2})-(\d{2})/ +let res=text.replace(reg,'$3/$2/$1')//将yyyy-MM-DD转换为MM/DD/yyyy +console.log(res) +``` \ No newline at end of file diff --git "a/51 \347\250\213\350\210\234/20231213.md" "b/51 \347\250\213\350\210\234/20231213.md" new file mode 100644 index 0000000..47b80c8 --- /dev/null +++ "b/51 \347\250\213\350\210\234/20231213.md" @@ -0,0 +1,142 @@ +## tab栏切换 + +```html + + + +``` + +轮播图 + +```html + + +``` \ No newline at end of file diff --git "a/51 \347\250\213\350\210\234/20231214.md" "b/51 \347\250\213\350\210\234/20231214.md" new file mode 100644 index 0000000..4057199 --- /dev/null +++ "b/51 \347\250\213\350\210\234/20231214.md" @@ -0,0 +1,2433 @@ +## 第一单元 + +## 一. JS基础知识 + +### 1. JS的书写方式:行内、内嵌、外部 + +#### 行内式:写在body里 + +~~~ javascript + +~~~ + +#### 内嵌式:写在head里 + +~~~ javascript + +~~~ + +#### 外部式:新建一个my.JS文件 + +~~~ javas +alert('你好Js') +~~~ + +### 2. JS的输入与输出语句 + +| 方法 | 说明 | +| -------------------- | -------------------------------------------- | +| alert('内容') | 浏览器弹出警示框 | +| console.log('内容') | 浏览器控制台打印输入信息(给程序员测试用的) | +| prompt('内容') | 浏览器弹出输入框,用户可以输入 | +| document.write(内容) | 浏览器打印出该内容 | + +#### 3. 变量 + +~~~ javascript +//1.声明变量 +let age; +//2.赋值 +age = 18; +//3.输出结果 +console.log(age); +//4.变量的初始化 +let name = '张三'; +//5.用户输入并输出 +let name =prompt('请输入你的名字'); +alert(name); +//6.声明多个变量 +let age = 18, //前面是0就是八进制,0x十六进制 + name = '张三', + gz = 2000; +~~~ + +#### 4. 数据类型 + +##### (1) 数字型:number + +infinity,代表无穷大,大于任何数值 + +-infinty,代表无穷小,小于任何数值 + +NaN,Not a number,代表一个非数值 + +isNaN() 判断是否为非数字 + +##### (2) 字符串型:String + +字符串引号嵌套 (外双内单,外单内双) + +~~~ javascript +let str1 ='我是"高富帅"程序猿'; +let str1 ="我是'高富帅'程序猿"; +alert(str1.length); //显示str1的长度 +//模板字符串 外面用`` 里面${变量名} +let age = 20; +document.write(`我今年${age}岁了`); +~~~ + +字符串转义符:\n 换行 \\ \ 斜杆 \t 缩进 \b 空格 + +##### (3) 简单数据类型 + +布尔(true,false) undefined NaN null + +~~~ javascript +var flag = true; +var flag = false; +console.log(flag+1); //true 参与计算当1来看 +console.log(flag+1); //false 参与计算当0来看 +//如果一个变量声明未赋值,默认就是 undefined 未定义数据类型 +var str; +var a1 = undefined; +console.log(a1+'张三'); //undefined张三 +console.log(a1+1); //NaN undefined和数字相加最后结果是NaN +// null 空值 +var space = null; +console.log(space+'张三');//null张三 +console.log(space+1); //1 +~~~ + +##### (4)获取变量数据类型 + +~~~ javascript +let num = 18; +console.log(typeof num); //number +//特殊 +let a1 = null; +console.log(typeof null); //object (对象) +~~~ + +#### 5. 常量 + +概念:使用 const 声明的变量称为"常量" + +使用场景:当某个变量永远不会改变的时候,就可以使用 const 来声明,而不用 let + +例: + +~~~ javascript +const PI =3.14; //声明的时候必须赋值,声明后不允许改变 +~~~ + +#### 6. 数据的转换 + +##### 1. 隐式转换 + +某些运算符执行时,系统内部自动将数据类型进行转换,这种转换为隐式转换 + +规则: + + +号两边只要有一个字符串,都会把另一个转成字符串 + + 除了+以外的算术运算符 比如 - * / 等都会把数据转成数字类型 + +缺点:转换类型不明确,靠经验才能总结 + +~~~ javascript +console.log(1+1) //2 +console.log(1+'pink') //1pink +console.log('2'-'2') //0 +console.log(+'123') //转换为数字123 +~~~ + +##### 2. 显式转换 + +编写程序时过度依靠系统内部是隐式转换是不严禁的,因为隐式转换规律并不清晰,大多是靠经验总结的规律。为了避免隐式转换带来的问题,通常根逻辑需要对数据进行显示转换。 + +转换为数字型 + +**Number(数据)** + + 转换数字类型 + + 如果该里的数据为非数字,将显示NaN(不是一个数字) + + NaN也是number类型的数据,代表非数字 + +**parselnt(数据)** + + 只保留整数 + +**parseFloat(数据)** + + 可以保留小数 + +#### 7. 比较运算符 + + > < >= <= == + +特殊: + + === 左右两边是否类型和值都相等 (全等) + + !== 左右两边是否不全等(不全等) + +~~~ javascript +console.log(2 == '2') //隐式转换 只判断值,不考虑数据类型 true +console.log(2 === '2') //判断值和数据类型都一样才行 false +console.log(NaN === NaN) //NaN 不等于任何人,包括自己 false +console.log(2 !== '2') //与 === 相反 true +~~~ + +字符串的比较:通过ASCII码表 + + 从左往右依次比较 + + 如果第一位一样再比较第二位,以此类推 + +~~~ javascript +console.log('a'<'b') //true +console.log('aa'<'ab') //true +console.log('aa'<'aac') //true +~~~ + +总结:NaN 不等于任何人,包括自己。 + + 尽量不要比较小数,因为小数有精度问题(将小数转为整数比较再转回小数) + + 不同类型之间比较会发生隐式转换 + +#### 8. 逻辑运算符 + +! > && > || + +~~~ javascript +let d = !false || true && false //true +~~~ + +**补充:所有数字都是True,只有0为False** + + **所有字符串都是True,只有空字符串(' ') 为False** + +#### 9. 三元运算符 + +利用三元运算符补零:大于10前面补零(01,02,03...) + +~~~ javascript +let num = prompt("请输入一个数字:") +num = num < 10 ? 0 + num : num +alert(num) +~~~ + +### 10. 数组 + + **数组中可以存放任意类型的数据** + +**数组的定义:** + +~~~ javascript +//方式一: +let arr =[1,'p',true,"张三"] //常用 +//方式二: +let arr = new Array(1,'p',true,"张三") //了解即可 +~~~ + +**数组的增、删、改、查:** + +~~~ javascript +let arr =['red'] +//增,可一次性增加多个 +arr.push('pink','green') //尾部插入 ['red','pink','green'] 并表示数组的新长度(3) +arr.unshift('black') //开头插入 ['black','red','pink','green'] +//删,可重复使用 +arr.pop() //删除数组的最后一个元素 +arr.shift() //删除数组的第一个元素 +arr.splice(1,2) //格式:arr.splice(起始位置,删除几个元素) 如果不指名删几个,默认删除后面所有 +//改 +arr[0]='gray' +//查 +document.write(arr[0]) +~~~ + +例:筛选出数组中大于10的数据 + +~~~ javascript + let arr =[1,12,56,48,5,98,4] + let newarr =[] + for(let i =0; i=10){ + newarr.push(arr[i]) + } + } + document.write(newarr) +~~~ + +##### 数组排序函数 + +~~~ javascript +let arr = [9,23,45,12,6,28] +arr.sort(function(a,b){ + // return a - b 升序 + // return b - a 降序 +}) +~~~ + +## 第二单元 + +### 1.函数:抽取-分装 (将相同的逻辑代码“包裹”成一个方法) + +~~~ javascript +function sheet99(){ + // 分装的内容 +} +// 调用方法 +sheet99() +~~~ + +1. 有参函数 + +~~~ javascript +// 求某个范围的累加和 +function gatSun(start,end){ + let sum = 0 + for(let i = start,i <= end,i++){ + sum = sum +i + } + console.log(sum) +} +// 调用方法 +gatSun(1,50) +gatSun(50,100) +~~~ + +2. 默认参数 (让程序更严谨) + +~~~ javascript +function getSum(x = 0,y = 0){ + document.write(x + y) +} +// 调用方法 +getSum(1,50) // 有参覆盖值 +getSum() // 无参使用默认值0 +// 实参可以是变量 +let x = 20 +let y = 30 +getSum(x,y) +~~~ + +3. 函数的返回值 + +~~~ javascript +function getSum(x = 0,y = 0){ + return x + y +} +// 调用方法 +let sum = getSum(1,2) +console.log(sum) +~~~ + +4. 匿名函数(没有函数名的函数) + +~~~ javascript +// 函数表达式 +// 将一个匿名函数赋值给一个变量 +let fn = function (x,y){ + console.log(x + y) +} +fn(1,2) +~~~ + +匿名函数 与 具名函数 的不同:.具名函数的调用可以写到任何地方,而匿名函数不行,因为匿名函数需先定义在使用 + +5. 立即执行函数(不需要调用就可以执行) + +~~~ javascript +// 语法1:(function(){})(); +// 语法1:(function(){}()); +(function(){ + console.log(20) +})(); // 多个立即执行函数之间需要分号隔开 +(function(){ + console.log(30) +})(); +// 立即执行函数本质是需要调用的 +(function(x,y){ + console.log(x + y) +})(1,2); // 这里的 小括号(1,2) 就表示方法的调用 +~~~ + +### 2. 对象 + +对象:在 javascript 里对象是一种数据类型,==无序的集合== + +对象是由==属性==和==方法==组成的 + +语法: + +~~~ javascript +let 对象名 = {} +//例: +let obj = { + uname: '张三', + age: 18, + gender:'男' +} +// 打印对象 +console.log(obj) // 显示一个集合 +~~~ + +对象的增、删、改、查 + +~~~ javascript +let obj = { + gName: '小米10青春版', //多个属性或方法之间用逗号隔开 + num: '152623024', + weight: '0.55kg', + address: '中国' +} +// 查 +console.log(obj.name) //方法一 +console.log(obj['name']) //方法二 +// 改 +obj.weight = '0.25kg' +// 增 +obj.price = 1999 +// 删 +delete obj.weight +~~~ + +对象里的方法 (对象里的函数,也就是方法) + +~~~ javascript +let myObj = { + uname: '张三', + // 方法 + getSum: function(x,y){ + console.log(x + y); + } +} +// 调用对象里的方法 +myObj.getSum(1,2) +~~~ + +遍历对象(获取对象中的每一个值) + +~~~ javascript +let student = { + uname: '张三', + age: 18, + sex: '男' +} +for(let k in student){ +// k相当于获取对象的属性名,获取的是字符串型的 + console.log(student[k]); //表示获取属性值,用查询的第二种方法 +} +~~~ + +遍历数组对象 + +~~~ javascript + //定义一个存放多个学生对象的数组 +let students = [ + { uname: '小明', age: 18, sex: '男' }, + { uname: '小红', age: 19, sex: '女' }, + { uname: '小刚', age: 20, sex: '男' }, + { uname: '小利', age: 22, sex: '女' } +] +//遍历获取根据索引获取每个对象 +for (let i = 0; i < students.length; i++) { + let index = students[i] + //根据对象获取属性值 + for (let k in index) { + console.log(index[k]); + } +} +~~~ + +内置对象 - Math + +~~~ javascript +//向上取整 +console.log(Math.ceil(1.1)); //2 +console.log(Math.ceil(1.9)); //2 +//向下取整 +console.log(Math.floor(1.1)); //1 +console.log(Math.floor(1.9)); //1 +//四舍五入 +console.log(Math.round(1.49)); //1 +console.log(Math.round(1.5)); //2 +console.log(Math.round(-1.5)); //-1 +console.log(Math.round(-1.51)); //-2 +//pow:幂运算 abs:绝对值 sqrt:求平方根 +~~~ + +内置函数 - 随机数 random() [0,1) + +~~~ javascript +// 0 ~ 10 之间的整数 +console.log(Math.floor(Math.random() * 11)) +// N ~ M 之间的随机数 +Math.floor(Math.random() * (M - N +1) + N) +// 获取一个指定范围的随机整数 + let getRd = function(N,M){ + return Math.floor(Math.random() * (M - N +1)+N) +} +console.log(getRd(5,10)); +~~~ + +### 3. APIs + +#### 1.作用和分类 + +作用:就是使用 JS 去操作 HTML 和浏览器 + +分类:==DOM (文档对象模型)==,==BOM (浏览器对象模型)== + +#### 2. 什么是DOM + +DOM是用来显现以及与任意 HTML 或 XML 文档交互的 API + +DOM是浏览器提供的一套专门用来==操作网页内容==的功能 + +作用:开发网页内容特效和实现用户交互 + +#### 3.什么是DOM树 + +将 HTML 文档以树状结构直观的表现出来,称为文档树或 DOM 树 + +作用 :==文档树直观的体现了标签与标签之间的关系== + +#### 4.什么是DOM对象 + +DOM对象:浏览器根据 HTML 标签生成的JS对象 + + 所有的标签属性都可以在这个对象上面找到 + + 修改这个对象的属性会自动映射到标签身上 + +DOM的核心思想:==把网页内容当做对象来处理== + +#### 5.document 是什么 + +是网页中最大的一个对象,网页所以内容都在 document 里面 + +#### 6.根据CSS选择器来获取DOM元素 + +语法1:选择匹配的第一个元素 + +~~~ javascript + document.querySelector('css选择器') +~~~ + +例: + +~~~ html +
测试
+ +~~~ + +语法2:选择匹配的多个元素 + +~~~ javascript + document.querySelectorAll('css选择器') +~~~ + +例: + +~~~ html + + +~~~ + +循环遍历(伪数组)或取其每一个对象 + +~~~ html + + +~~~ + +#### 7.操作元素内容 + +元素:**innerText** 属性 (显示纯文本,不解析标签) + +~~~ html +
看看我可不可以变
+ +~~~ + +元素:**innerHTML** 属性 (解析标签) + +~~~ html +
看看我可不可以变
+ +~~~ + +扩充 + +~~~ javascript +body{ + background : url(背景图片地址) no-repeat top center/cover; + // 取消背景图片平铺,居中全屏 +} +~~~ + +#### 8.操作元素样式属性 + +1.通过**style**属性修改样式 + +~~~ html + + +
+ +~~~ + +2.通过类名修改样式 + +~~~ html + + + + +~~~ + +3.通过 **classList** 操作类控制 css + +为了解决 className 容易覆盖以前的类名,我们可以通过 classList 方式追加和删除类名 + +**add()**:添加类 **remove()**:删除类 **toggle()**:切换类,有就删除没有就添加 + +**contains()**:看看有没有包含某个类,有返回 true ,没有就返回 false + +~~~ html + + +
abc
+ +~~~ + +4.修改表单属性 + +~~~ html + + + + +~~~ + +5.自定义属性 + +标准属性:标签天生自带的属性,如:class id title + +自定义属性: + + 在html5中推出来了专门的 **data-自定义属性**,在标签一律用**data-开头** + + 在DOM对象上一律以**dataset**对象方式获取 + +~~~ html + +
盒子
+//获取自定义属性 + +~~~ + +#### 9.定时器 + +语法:**setInterval(执行语句,秒数)** + +~~~ html + +~~~ + +#### 10.事件 + +事件:事件是在编程时系统内发生的动作或者发生的事件,如:用户单击按钮 + +**1.事件监听**:就是程序检查是否有事件产生,一旦有事件触发,就立即调用一个函数做出响应 + +语法:**元素对象 . addEventListener(‘事件类型’,要执行的函数)** + +~~~ html + + +~~~ + +**2.事件类型** + +1.鼠标事件:**click**(鼠标点击) **mouseenter**(鼠标经过) **mouseleave**(鼠标离开) + +2.焦点事件:**focus**(获取焦点) **blur**(失去焦点) + +3.键盘事件:**keydown**(键盘按下触发) **keyup**(键盘抬起触发) + +4.文本事件:**input**(用户输入事件) + +5.**change**事件:当鼠标离开了表单,并且表单值发生了变化时触发 + +**3.事件对象** + +事件对象:也是个对象,这个对象里有事件触发时的相关信息 + +例如:鼠标点击事件中,事件对象就存了鼠标点在那个位置等信息 + +使用场景:可以判断用户按下哪个键,或哪个元素,从而做相应的操作 + +语法:事件对象在,事件函数里的第一个参数 + +~~~ javascript +btn.addEventListener('click',function(e){ + alert('点我干嘛!') + }) +~~~ + +**事件对象常用属性** + +**type**:获取当前的事件类型 + +**clientx / clienty**:获取光标相对于浏览器可见窗口左上角的位置(x,y) + +**offsetx / offsety**:获取光标相对于当前DOM元素左上角的位置 + +**key**:获取用户按下键盘的值 + +~~~ html + + +~~~ + +**4.环境对象** + +环境对象:指的是函数内部特殊的**变量 this**,他代表 着当前函数运行时所处的环境 + +作用:弄清楚 this 的指向。 **谁调用,this就是谁** + +比如:按钮添加了事件,那么this就是这个按钮(指向这个按钮) + +**5.回调函数** + +如果将函数 A 做为参数传递给函数 B 时,我们称函数 A 为回调函数 + +~~~ javascript +//场景一 +function fn(){ + log('我是回调函数') +} +setInterval(fn,1000) //表示每一秒回头调用一下fn函数 +//场景二 +box.addEventListener('click',function(){ + log('我是回调函数') +}) //表示每点击一次,回头调用函数 +~~~ + +#### 11.事件流 + +事件流指的是事件完整执行过程中的流程路径 + +过程:事件捕获 => 事件目标阶段 => 事件冒泡 整个完整的过程就是事件流 + +![](图片/事件流.png) + +**事件捕获** + +概念:从DOM的根元素开始去执行对应的事件(从外到里) + +格式: + +~~~ html +DOM.addEventListener(事件类型,事件处理函数,是否使用捕获) +~~~ + +**事件冒泡** + +概念:当一个元素的事件被触发时,同样的事件将会在该元素的所有祖先元素中依次被触发,这个过程被称为事件冒泡 + +事件冒泡的必要性:如果没有冒泡给大盒子注册点击事件,点击的是里面的小盒子,会导致大盒子的点击无法执行 + +**阻止冒泡** + +~~~ javascript +事件对象.stopPropagation() +e.stopPropagation() +~~~ + +**阻止元素默认行为** + +~~~ javascript +e.preventDefault() //阻止提交事件,或a连接跳转 +~~~ + +**事件移除解绑** + +~~~ javascript +//添加点击事件 +事件对象.addEventListener('click',fn) +//移除点击事件 +事件对象.removeEventListener('click',fn) +~~~ + +**事件委托** + +事件委托:给父元素注册事件,当我们触发子元素的时候,会冒泡到父元素身上,从而触发父元素的事件 + +优点:减少注册次数,提高程序性能 + +~~~ html + + + +~~~ + +#### 12.其他事件 + +1.页面加载事件 + +事件名:**load** + +加载外部资源(如图片、外联css、javaScript等)加载完毕时触发的事件 + +~~~ javascript +// 在页面加载完之后,回头调用这个函数,写在head里的script +标签对象.addEventListener('load',function(){ + //执行的代码 +}) +~~~ + +事件名:**DOMContentLoaded**(比 load 加载速度更快) + +当初始的 HTML 文档被完全加载和解析完成之后,该事件被触发,而无需等待样式表、图像等完全加载 + +~~~ javascript +//无需等待样式表、图像等完全加载 +document.addEventListener('DOMContentLoaded',function(){ + //执行的代码 +}) +~~~ + +2.页面滚动事件 + +事件名:**scroll** + +滚动条在滚动的时候持续触发的事件 + +场景:很多网页需要检测用户把页面滚动到某个区域后做一些处理,比如固定导航栏,返回顶部 + +~~~ javascript +// 监听整个页面滚动 +window.addEventListener('scroll',function(){ + // 执行的代码 +}) +~~~ + +页面滚动事件 - 获取位置 + +关键字:**scrollLeft 和 scrollTop** (属性) + +获取 div 滚动的长度 (px) + +~~~ html + +~~~ + +获取页面滚动的长度 + +~~~ javascript +//页面滚动事件 + window.addEventListener('scroll',function(){ + //获取 HTML(页面)滚动的长度 + const n = document.documentElement.scrollTop + //判断,如果页面滚动100就显示div + if(n >=100){ + div.style.display = 'block' + }else{ + div.style.display = 'none' + } + }) +//document.documentElement.scrollTop = 800 修改页面的滚动长度为800 +~~~ + +3.页面尺寸事件 + +会在窗口尺寸改变的时候触发事件:**resize** + +~~~ javascript +window.addEventListener('resize',function(){ + //执行代码 +} +~~~ + +获取页面宽高:**clientWidth 和 clientHeight** + +获取元素的可见部分宽高==(不包含边框,margin,滚动条等)== + +~~~ javascript +const diw = document.querySelector('div') +// 通过js获取div的宽度 +log(div.clientWidth) +~~~ + +检测屏幕宽度 + +~~~ javascript +window.addEventListener('resize',function(){ + let w = document.documentElement.clientWidth + log(w) + ) +~~~ + +获取元素尺寸位置 + +获取宽高:获取元素的自身宽高、==包含元素自身设置的宽高、padding、border== + + 关键字:**offsetWidth 和 offsetHeight** + + 注意:获取的是可视宽高,如果盒子是隐藏的,获取结果是0 + +获取位置:获取元素距离自己定位父级元素的左、右距离 + + 关键字:**offsetLeft 和 offsetTop** 注意是只读属性 + +#### 总结 + +| 属性 | 作用 | 说明 | +| --------------------------- | ---------------------------------------- | ---------------------------------------------------------- | +| scrollLeft 和 scrollTop | 被卷去的头部和左侧 | 配合页面滚动来用,==可读写== | +| clientWidth 和 clientHeight | 获取元素宽度和高度 | 不包含边框,margin,滚动条,用于js获取元素的大小,只读属性 | +| offsetWidth 和 offsetHeight | 获取元素宽度和高度 | ==包含边框,margin,滚动条,只读== | +| offsetLeft 和 offsetTop | 获取元素距离自己定位父级元素的左、上距离 | 获取元素位置的时候使用,只读 | + +#### 补充: + +~~~ javascript +//1.让滚动条丝滑的滚动 +html{ + scroll-behavior: smooth +} +//2.重置表单 +表单.reset() +//3.弹出有确认和取消的警示框,返回 true 或 false +confirm('你确定要删除这条数据吗?') +~~~ + +#### 13.日期对象 + +日期对象:用来表示时间的对象,可以得到当前系统的时间 + +实例化:在代码中发现了new关键字,一般将这个操作称为实例化 + +1.获取当前时间 + +~~~ javascript +const date = new Date() +~~~ + +2.获取指定时间 + +~~~ javascript +const date = new Date('2023-10-2 20:12:25') +~~~ + +3.日期对象方法 + +| 方法 | 作用 | 说明 | +| ------------- | ------------------ | ---------------------------- | +| getFullYear() | 获取年份 | 获取四位年份 | +| getMonth() | 获取月份 | 取值为 0 ~ 11 ==要手动加一== | +| getDate() | 获取月份中的第几天 | 不同月份取值也不同 | +| getDay() | 获取星期 | 取值为 0~ 6 ==星期天是0== | +| getHours() | 获取小时 | 取值为 0~ 23 | +| getMinutes() | 获取分钟 | 取值为 0~ 59 | +| getSeconds() | 获取秒 | 取值为 0~ 59 | + +~~~ javascript +const date = new Date() +div.innerHTML = date.toLocaleString() // 2023/10/2 20:33:26 +~~~ + +4.时间戳(毫秒数) + +使用场景:如果计算倒计时效果,就需要借助于时间戳完成 + +算法:将来的时间戳 - 现在的时间戳 = 剩余时间毫秒数 + +获取时间戳:现在 距 1970年01月01号,已经过去了多少毫秒 + +~~~ javascript +//1. getTime()方法 +const date = new Date() +log(date.getTime()) +//2. +new Date() 隐式转换 +log(+new Date()) +//3. Date.now() 无须实例化,只能得到当前时间戳,前两种可以返回指定时间的时间戳 +log(Date.now()) +//获取指定时间的时间戳 +log(+new Date('2023-10-2 23:30:00')) +~~~ + +**毫秒转换公式**: + +~~~ javascript +d = parseInt(总秒数 / 60 / 60 / 24); //计算天数 +h = parseInt(总秒数 / 60 / 60 % 24); //计算小时 +m = parseInt(总秒数 / 60 % 60); //计算分钟 +s = parseInt(总秒数 % 60); //计算秒数 +~~~ + +#### 14.节点操作 + +**DOM节点**:DOM树里每一个内容都称之为节点 + +节点类型 + + 元素节点:所有的标签,比如:body、div, HTML 是根节点 + + 属性节点:所有的属性,比如:href、id、class + + 文本节点:所有的文本 + +**查找节点** + +父节点查找:**parentNode** 属性,返回最近一级的父节点,找不到返回 null + +~~~Html +
+
+
x
+
+
+ +~~~ + +子节点查找 + + childNodes:获取所有子节点、包括文本节点(空格、换行)、注释节点等 + + **children** 属性(重点):仅获得所有元素节点,返回一个伪数组 + +~~~ Html + + +~~~ + +兄弟关系查找 + + 下一个兄弟节点:**nextElementSibling** 属性 + + 上一个兄弟节点:**previousElementSibling** 属性 + +~~~ html + + +~~~ + +**增加节点** + +创建节点:**createElement** + + 创建一个新的网页元素,再添加到页面内,一般先创建节点,在插入节点 + +追加节点:将创建的节点插入到某个父元素中 + + 插入到父元素的最后一个子元素:**appendChild(要插入的元素)** + + 插入到某个子元素的前面:**insertBefore(要插入的元素,在哪个元素前面)** + +~~~ Html + + +~~~ + +克隆节点:**cloneNode(布尔值)** + + 复制一个原节点,把复制的节点放入到指定的元素内部 + + 若为 true,则代表克隆时会包含后代节点一起克隆(克隆所有) + + 若为 false,则代表克隆时不包含后代节点,默认为 false(只克隆标签,里面的内容不克隆) + +~~~ html + + +~~~ + +**删除节点** + +要删除元素必须==通过父元素删除==,如果不存在父子关系则删除失败 + +语法:父元素**.removeChild**(要删除的元素) + +~~~ Html + + +~~~ + +#### 15.M端事件 + +**移动端触摸事件 touch** + +| 触摸touch事件 | 说明 | +| ------------- | ----------------------------- | +| touchstart | 手指触摸到一个DOM元素时触发 | +| touchmove | 手指在一个DOM元素上滑动时触发 | +| touchend | 手指从一个DOM元素上移开时触发 | + +#### 16.Window 对象 + +**1. DOM(Browser Object Model) 是浏览器对象模型** + + window对象是一个全局对象,是JavaScript中的顶级对象 + + 像 document、alert()、log()都是window的属性基本BOM的属性都是window的 + + 所有通过var定义在全局作用域中的变量、函数都会变成window对象的属性和方法 + +**2. 定时器 - 延时函数** + + 延迟执行的函数:**setTimeout**,只执行一次 + + 语法:**setTimeout (回调函数,等待的毫秒数)** + + 清除延时函数: + +~~~ javascript +let timer = setTimeout (回调函数,等待的毫秒数) +clerTimeout(timer) +~~~ + +**3. JS执行机制** + + 单线程,同一时间只能做一件事,所有任务排队执行,会遇到堵塞的可能 + + 为了解决这个问题,HTML5 提出 Web Worker 标准,允许JS脚本创建多个线程,于是有了**同步**和**异步** + + **同步**:所有的任务都要按照顺序执行 如:等开水开了再去切菜 + + **异步**:执行任务遇见堵塞时,在堵塞的同时,处理其他的任务 如:在烧开水的同时,去切菜 + + 耗时少的为同步任务,耗时多的为异步任务,**先执行完同步任务,在回头去执行异步任务** + + 同步任务交个JS处理,异步任务交个浏览器处理 + + 主线程不断获取任务并执行任务,这种机制被称为**事件循环(event loop)** + +**4. location** :数据类型是对象,它拆分并保存了 URL 地址的各个组成部分 + + 常用属性和方法: + + **href** 属性获取完整的 URL 地址,对其赋值时用于地址的跳转 + + **search** 属性获取地址中携带的参数,符号 ?后面部分 + + **hash** 属性获取地址中的哈希值,符合 # 后面部分 + +~~~ javascript +location.href = 'http://www.baidu.com' +location.search +location.hash +~~~ + + **reload()** 方法用来刷新当前页面,传入参数true时表示强制刷新 + +~~~ html + + +~~~ + +**5. navigator** 对象:该对象下记录了浏览器自身的相关信息 + + 通过 **userAgent** 检测浏览器的版本及平台 + +**6. history** 数据类型对象 + + 主要管理历史记录,该对象与浏览器地址栏的操作相对应,如:前进、后退、历史记录等 + + 常用属性和方法: + +| history对象方法 | 作用 | +| --------------- | ----------------------------------------------------------- | +| back() | 后退功能 | +| forward() | 前进功能 | +| go(参数) | 前进后退功能,参数如果是1 前进1个页面,如果是-1后退一个页面 | + +#### 17. 本地存储 + +- 数据存储在用户浏览器中 +- 设置、读取方便、甚至**页面刷新不丢失数据** + +**本地存储分类 - localStorage** + + 作用:可以将**数据永久存储在本地**(用户的电脑),除非手动删除 + + 特性:可以多窗口(页面)共享(同一浏览器可以共享),**以键值对的形式存储使用** + +~~~ html + +~~~ + +**本地存储分类 - sessionStorage** + + 特性:生命周期为关闭浏览器窗口,数据消失 (其他用法跟上面一样) + +**存储复杂数据类型** + + 解决:需要将复杂数据类型转换成 JSON 字符串,在存储到本地 + +~~~ html + +~~~ + +**字符串拼接新思路**:(效果更高,开发常用的写法) + + 利用 **map()** 和 **join()** 数组方法实现字符串拼接 + + **map() 方法**:可以遍历数组处理数据,并且返回新的数组 + + **join() 方法**:用于把数组中的所有元素转换成一个字符串 + +~~~ html + +~~~ + +#### 18.正则表达式 + + 正则表达式:是用于匹配字符串中字符组合的模式,通常用来查找、替换 + + 正则表达式的使用:**test()** **exec()** + +~~~ html + +~~~ + +**元字符** + + 是一些具有特殊含义的字符 + + 如:普通字符:abcdefg …. 元字符:[a-z] + +**1.边界符**:用来提示字符所在的位置 + +| 边界符 | 说明 | +| ------ | ------------------------------ | +| **^** | 表示匹配行首的文本(以谁开始) | +| **$** | 表示匹配行尾的文本(以谁结束) | + + 如果 ^ 和 $ 在一起,表示必须是精确匹配,只能是这两个边界符夹着的字 + +**2.量词**:设定某个模式出现的次数 + +| 量词 | 说明 | +| --------- | ---------------------------- | +| ***** | 重复零次或多次(>=0) | +| **+** | 重复一次或多次(>=1) | +| **?** | 重复零次或一次(0 \|\|1) | +| **{n}** | 必须重复 n 次 | +| **{n,}** | 重复 n 次或更多次(>=n) | +| **{n,m}** | 重复 n 到 m 次(>=n && <=m) | + +**3.元字符**:[abc] 匹配字符集合,只要包括其中一个就行,只选1个 + +**字符类** + + 使用连字符 - 表示一个范围 + + 如:[a-z] 表示 a 到 z 26个英文字母都可以 + + [a-zA-z] 表示大小写英文字母都可以 + + [0-9] 表示 0 - 9 的数字都可以 + + [ ] 里面加上 ^ 表示取反符号 如:[ ^ a-z] 除了小写字母以外的字符 + + **.** 匹配换行符之外的任何单个字符 + +**预定类**:指的是 某些常见模式的简写方式 + +| 预定类 | 说明 | +| ------ | ------------------------------------------------------------ | +| \d | 匹配 0-9 之间的任一数字,相当于 [0-9] | +| \D | 匹配所有 0-9 以外的字符,相当于 [ ^0-9] | +| \w | 匹配任意的字母、数字和下划线,相当于 [A-Za-z0-9_] | +| \W | 除所有字母、数字和下划线以外的字符,相当于 [ ^A-Za-z0-9_] | +| \s | 匹配空格(包括换行符、制表符、空格符等),相当于 [\t\r\n\v\f] | +| \S | 匹配非空格的字符,相当于 [ ^\t\r\n\v\f] | + + **4.修饰符** + + 修饰符约束正则执行的某些细节行为,如是否区分大小写、是否支持多行匹配 + + 语法: /表达式/修饰符 + +- i 是单词 ignore 的缩写,正则匹配时字母不区分大小写 +- g 是单词 global 的缩写,匹配所有满足正则表达式的结果 + +~~~ html + +~~~ + +### 第三单元 + +#### 1. 作用域 + +规定了变量能够被访问的 “范围” + +**局部作用域** + +- 函数作用域: + - 在函数内部声明的变量,外部无法直接访问 + - 函数的参数也是函数内部的局部变量 + - 不同函数内部声明的变量无法互相访问 + - 函数执行完毕后,函数内部的变量实际被清空了 + +- 块作用域: + - 使用 {} 包裹的代码为代码块,其内部声明的变量,外部无法访问 + - let 声明的变量会产生块作用域,var 不会产生块作用域 + - const 声明的常量也会产生块作用域 + - 不同代码块之间的变量无法互相访问 + +**全局作用域** + +script 标签和 .js文件的【最外层】就是全局作用域 + +**作用域链** + +本质上是底层的==变量查找机制== + +- 在函数执行时,会==优先查找当前==函数作用域中的变量 +- 如果当前作用域查不到则会依次==逐级查找父级作用域==直到全局作用域 + +总结: + +- 嵌套关系的作用域串联起来形成2了作用域链 +- 相同作用域链中按着从小到大的规则查找变量 +- 子作用域能够访问父作用域,父级作用域无法访问子级作用域 + + **垃圾回收机制**(生命周期) + +- 内存分配:当我们声明变量、函数、对象的时候,系统会自动为它们分配内存 +- 内存使用:即读写内存,也就是使用变量、函数等 +- 内存回收:使用完毕,由==垃圾回收器==自动回收不再使用的内存 + +说明:全局变量一般在关闭页面后回收,局部变量不用了就会自动回收 + +内存泄漏:程序中分配的==内存==由于某种原因程序==未释放==或==无法释放==叫做==内存泄漏== + +**闭包** + +概念:一个函数对周围状态的引用捆绑在一起,内层函数中访问到其外层函数的作用域 + +简单理解:闭包 = 内层函数 + 外层函数的变量 ==可能会有内存泄漏的问题== + +~~~ javascript +//内部使用外部 +function outer(){ + const a = 10 + function fn(){ + log(a) // 内部函数使用外部变量 + } + fn() +} +outer() +~~~ + +~~~ javascript +//外部使用内部 +function outer(){ + const a = 10 + function fn(){ + log(a) + } + return fn //将内部函数,返回给外部函数 +} +const fun = outer() //拿变量接收内部函数 +fun() //调用内部函数 +~~~ + +实现数据的私有:防止 i 被修改,如果 i 定义在函数外面,全局变量容易被改,不安全 + +~~~ javascript +function fn(){ + let i = 1 + function fun(){ + i++ + log(`函数被调用了${i}次`) + } + return fun +} +const result = fn() +result() // 2 +result() // 3 +~~~ + +**变量提升** + +~~~ javascript +//1.把所有 var 声明的变量提升到 当前作用域的最前面 +//2.只提升变量声明,不提升变量赋值 +log(num+'件') // undefined件 +var num = 10 +log(num) // 10 + +//相当于 +var num +log(num+'件') +num = 10 +log(num) +~~~ + +#### 2. 函数进阶 + + **函数提升** + +~~~ javascript +//1. 会把所有函数声明提升到当前作用域的最前面 +//2. 只提升函数声明,不提升函数调用 +fn() +function fn(){ + log('函数提升') +} +~~~ + +总结: + +- 函数提升能够使函数的声明调用更灵活 +- 函数表达式不存在提升 +- 函数提升出现在当前作用域当中 + +**函数参数** + +- **动态参数:arguments** 是函数内部内置的伪数组,它包含调用函数时传入的所有实参 + +~~~ javascript +function getSum(){ + let sum = 0 + for(let i = 0;i <= arguments.length;i++){ + sum = sum + arguments[i] + } + log(sum) // 35 +} +getSum(5,10,20) +~~~ + +总结: + +- arguments 是个伪数组,只存在于函数中 +- arguments 的作用是动态获取函数的实参 +- 可以通过 for 循环依次得到传递过来的实参 + +**剩余参数**(类似java的可变参数 …num) + +- 允许我们将一个不定数量的参数表示为一个**真数组**(常用) + +~~~ javascript +// 表示前两个实参被a和b形参接收,后面的实参被arr数组接收 +function getSum(a,b,...arr){ + log(arr) +} +getSum(1,2) // [] +getSum(1,2,3,4,5) // [3,4,5] +~~~ + +**展开运算符**:可以展开数组 + +~~~ javascript +const arr1 = [1,2,3] +log(...arr) // 1 2 3 ...arr1 === 1,2,3 +//1.求数组中的最大值 +//log(Math.max(1,2,3)) +log(Math.max(...arr1)) // 3 +//2.合并数组 +const arr2 = [4,5,6] +const arr =[...arr1, ...arr2] +log(arr) // [1,2,3,4,5,6] +~~~ + +**箭头函数(重要)** + +- 需要匿名函数或函数表达式的地方,更适用箭头函数,可以简化代码 + +基本语法 + +~~~ javascript +/* +const fn = function(){ + log(123) +} +*/ +//1.箭头函数,基本语法 +const fn = () => { + log(123) +} +//2.只有一个形参的时候,可以省略小括号 +const fn = x => { + return x + x +} +fn(1) +//3.只有一行执行代码的时候,大括号和 return +const fn = x => x + x +log(fn(1)) //2 +//4.箭头函数可以直接返回一个对象 +const fn = (uname) => ({uname:uname}) +fn('pink老师') +~~~ + +箭头函数参数:没有 arguments 动态参数,但是有==剩余参数== …args + +箭头函数 this:不会创建自己的 this,它只会从作用域链的上一层找 + +~~~ javascript +const obj = { + uname:'pink老师' + sayHi:function(){ + let i = 10 + const count = () => { + log(this) //此时this指向obj + } + count() + } +} +obj.sayHi +~~~ + +#### 3. 解构赋值 + +- 将数组的单元值快速批量,赋值给一系列变量的简洁语法 + +**数组解构** + +~~~ javascript +// 将数组中的值依次赋值给变量 +const arr = [100,60,80] +// const max = arr[0] +// const min = arr[1] +// const avg = arr[2] +const [max,min,avg] = arr +// 典型应用,交换2个变量 +let a = 1 +// 立即执行函数、数组开头时,前面有代码要加分号,不然会和前面语句连在一起执行 +let b = 2; +[b,a] = [a,b] +log(a,b) // 2 1 +~~~ + +~~~ javascript +//1. 变量多,单元值少,变量undefined +const [a,b,c,d] = [1,2,3] +//2. 变量少,单元格多 +const [a,b] = [1,2,3] +//3. 剩余参数,变量少,单元值多 +const [a,b, ...c] = [1,2,3,4,5] +//4. 防止 undefined 传递(给变量赋默认值) +const [a = 0,b = 0] = [] +const [a = 0,b = 0] = [1,2] //覆盖默认值 +~~~ + +**对象解构** + +~~~ javascript +const obj = { + uname: 'pink老师', + age: 18 +} +//1. 对象解构语法 +//要求:变量名必须与属性名一致 +// const {uname,age} = obj +const {uname,age} = {uname: 'pink老师',age: 18} +log(uname,age) +// 解构的变量名,可以重新该值 +const {uname: username,age} = {uname: 'pink老师',age: 18} +log(username,age) +//2. 数组对象解构 +const pig = [ + { + uname: '佩奇', + age: 6 + } +] +const [{uname,age}] = pig +//3. 多级对象解构 +//要求:指名是哪个对象 +const pig = { + uname: '佩奇', + family: { + mother: '猪妈妈' + father: '猪爸爸' + brother: '乔治' + }, + age: 6 +} +const {uname,family: {mother,father,brother},age} = pig +~~~ + +**forEach 方法(适合遍历数组对象)** + +与 map 方法 语法相同,但是 map 会返回一个新的数组,forEach 不会 + +~~~ javascript +遍历的数组.forEach(function(当前数组元素,当前元素索引){ + //函数体 +}) +~~~ + +**filter 方法(重点)** + +主要使用场景:==筛选数组符合条件的元素==,并返回筛选之后的新数组 + +~~~ javascript +const arr = [10,20,30] +const newArr = arr.filter(function(item,index){ + return item >= 20 +}) +log(newArr) // [20,30] +// 箭头函数写法 +const newArr = arr.filter(item => item >= 20) +~~~ + +#### 4.深入对象 + +**构造函数**:是一种特殊的函数,主要用来初始化对象 + +使用场景:==多个对象有相同属性,封装成一个构造函数== + +~~~ javascript +// 创建一个构造函数,首字母要大写 +function Pig(uname,age){ + this.uname = uname + this.age = age +} +// 创建对象 +const p1 = new Pig('佩奇',6) +const p2 = new Pig('乔治',4) +~~~ + +实例成员:通过构造函数创建的对象称之为实例对象,==实例对象中==的属性和方法称之为==实例成员==(实例属性和实例方法) + +- 为构造函数传入参数,创建结构相同但值不同的对象 +- 构造函数创建的实例对象彼此独立互不影响 + +静态成员:构造函数的属性和方法被称为静态成员(静态属性和静态方法) + +- 静态成员只能构造函数访问 +- 静态方法中 this 指向构造函数 + +~~~ javascript +// 静态成员 +function Pig(name){ + this.name = name +} +Pig.eyes = 2 // 静态属性 +Pig.sayHi = function(){ + log(this) +} +Pig.sayHi() // 指向构造函数 +log(Pig.eyes) // 2 +~~~ + +#### 5.内置构造函数 + +其实字符串。数值。布尔等基本数据类型也都有专门的构造函数,称为包装类型 + +**Object** + +object 是内置的构造函数,用于创建普通对象 + +三个常用静态方法: + +- **Object.keys** 获取对象中的所有属性(键),返回数组 +- **Object.values** 获取对象中的所有属性值(值),返回数组 +- **Object.assign** 常用于对象拷贝(合并对象) + +~~~ javascript +const o = {uname: 'pink',age: 18} +log(Object.keys(o)) // [uname,age] +log(Object.values(o)) // ['pink',18] +// 拷贝 +const oo = {} +Object.assign(oo,o) // 将 o 对象拷贝给 oo 对象 +// 给对象追加属性 +Object.assign(o,{sex: '男'}) +log(o) // [uname: 'pink',age: 18,sex: '男'] +~~~ + +**Array** + +Array 是内置构造函数,用于创建数组 + +常用实例方法: + +| 方法 | 作用 | 说明 | +| ----------- | -------- | ---------------------------------------------------- | +| **forEach** | 遍历数组 | 不返回数组,经常用于==查找遍历数组元素== | +| **filter** | 过滤数组 | ==返回新数组==,返回==筛选满足条件==的数组元素 | +| **map** | 迭代数组 | ==放回新数组==,返回==处理之后==的数组元素 | +| **reduce** | 累计器 | 返回累计处理的结果,经常用于求和等 | +| **find** | 查找元素 | 返回符合条件的第一个数组元素值,没则有返回undefined | +| **every** | 检查数组 | 检查数组中所有元素,都满足某个条件,返回 true或false | +| **some** | 检查数组 | 检查数组中所有元素,有元素满足条件,返回 true或false | +| **concat** | 合并数组 | 合并两个数组,返回一个新数组 | +| **sort** | 排序数组 | 对原数组单元值进行排序 | +| **reverse** | 反转数组 | 将数组反转 | + +~~~ javascript +// 数组 reduce 方法 +const arr = [1,5,8] +//1. 没有初始值 +const total = arr.reduce(function(prev,current){ + return prev + current //上一次的值 + 当前的值 +}) +log(total) // 14 +//2. 有初始值 +const total = arr.reduce(function(prev,current){ + return prev + current //上一次的值 + 当前的值 +}.10) +log(total) // 24 +//3. 箭头函数写法 +const total = arr.reduce((prev,current) => prev + current, 10) +~~~ + +案例:有一个员工数组对象,计算当月支出多少薪资 + +~~~ javascript +const arr =[ + { + uname: '张三', + salary: 10000 + }, { + uname: '李四', + salary: 10000 + }, { + uname: '王五', + salary: 10000 + } +] +//一定要有初始值,否则默认第一个对象为初始值 +const total = arr.reduce((prev,current) => prev + current.salary, 0) +log(total) // 30000 +~~~ + +静态方法 **Array.from(数组)** 将伪数组转换为真数组 + +~~~ javascript +const lis = document.querySelectorAll('ul li') +const liArr = Array.from(lis) +~~~ + +**String** + +常见实例方法1: + +| 方法 | 说明 | +| --------------------------------------- | --------------------------------------------- | +| **split(’分隔符’)** | 将字符串转换为数组,和 join() 相反 | +| **substring(起始索引,结束索引)** | 截取字符串 | +| **startswith(检查字符串,检测开始索引)** | 检测是否以某字符开头,返回布尔值,endwith相反 | +| **includes(搜索的字符串,位置索引)** | 判断一个字符串是否包含某个字符 | + +**Number** + + **toFixed()** 设置保留小数位的长度 + +~~~ javascript +const num = 10.923 +log(num.toFixed(1)) //10.9 +log(num.toFixed(2)) //10.92 +log(num.toFixed()) //11 四舍五入 +~~~ + +#### 7.深入面向对象 + +**1. 编程思想** + +面向过程:就是按照我们分析好的步骤去解决问题(蛋炒饭) + +- 优点:性能比面向对象高 +- 缺点:没有面向对象易维护、易复用、易扩展 + +面向对象:是以对象功能来划分问题,而不是步骤(盖浇饭) + +- 优点:易维护、易复用、易扩展、更加灵活 +- 缺点:性能比面向过程低 + +**2. 原型** + +目的:为了解决构造函数浪费内存 + +**原型对象:prototype** + +- ==每个构造函数都有一个 prototype 属性==,指向另一个函数,称为原型对象 +- 可以把那些不变的方法,直接定义在 prototype 对象上,实现对象的实例==共享==这些方法 +- ==构造函数和原型对象中的 this 都指向 实例化的对象== + +~~~ javascript +//1. 创建构造函数 +function Star(uname,age){ + this.uname = uname + this.age= age + /* + 函数方法写在这里面,每 new 一次都会生成一个新的函数(浪费内存) + this.sing = function(){ + log('唱歌') + } + */ +} +//2. 利用 prototype 属性,解决浪费内存问题 +// 将函数方法定义在 prototype 对象上,实现共享函数 +Star.prototype.sing = function(){ + log('唱歌') +} +//3. 创建实例对象 +const ldh = new Star('刘德华',55) +const zxy = new Star('张学友',58) +ldh.sing() +zxy.sing() +log(ldh.sing === zxy.sing) // true +~~~ + +自己定义 数组扩展方法,求最大值 + +~~~ javascript +const arr = [1,2,3] +//自定义方法写到,数组.prototype 身上,任何实例化数组都能使用 +Array.prototype.max = function(){ + //展开运算符,此时 this 指向实例化对象(调用者 arr) + return Math.max(...this) +} +log(arr.max()) // 3 +~~~ + +**原型对象的 constructor 属性**:==指向==创建该原型对象的==构造函数== + +~~~ javascript +// 定义一个空属性的构造函数 +function Star(){} +// 自定义多个方法,用对象形式赋值 +Star.prototype = { +// 因为采取的是赋值,所以会覆盖原有的函数 constructor,从而找不到是谁构造函数里的 + // 需要重新指回这个原型对象的 构造函数 + constructor: Star, + sing: function(){ + log('唱歌') + }, + dance: function(){ + log('跳舞') + } +} +~~~ + +**对象原型:_ _proto_ _** + +==实例对象都有一个属性 _ _proto_ _ ,对象原型 指向构造函数的 prototype 原型对象== + +**对象原型的 constructor 属性**:==指向==创建该原型对象的==构造函数== + +![](图片/原型.png) + +**原型继承** + +~~~javascript +//1. 封装公共部分 +function Person() { + this.eays = 2, + this.head = 1 +} +//2. 创建女人的构造函数 +function Woman(){} +//3.1 Woman 通过原型来继承 Person +//3.2 将公共部分,放到该构造函数原型 prototype 上 +Woman.prototype = new Person() +//3.3 指回原来的构造方法 +Woman.prototype.constructor = Woman +//4. 创建女人对象 +const red = new Woman() +log(red) +// 创建男人以此类推 +~~~ + +**原型链** + +基于原型对象的继承使得不同构造函数的原型对象关联在一起,并且这种关联的关系是一种链状的结构,我们将原型对象的链状结构关系称为原型链 + +![](图片/原型链.png) + +#### 8.高级技巧 + +**1. 深浅拷贝** + +**浅拷贝**:简单数据类型拷贝值,引用数据类型拷贝的是地址(单层对象可以,多层对象有问题) + +~~~ javascript +const obj = { + uname: 'pink', + age: 18, + famliy: { + baby: '小pink' + } + // 浅拷贝 + // 方式一 + const o = {...obj} + o.age = 20 // 修改的是自己 obj 对象 值不变 + // 方式二 + Object.assign(o,obj) + o.age = 20 + o.famliy.baby = '老pink' // 因为是多层对象,所以 obj 也会跟着修改 +} +~~~ + +**深拷贝**:拷贝的是对象,不是地址 + + 1.通过**递归**实现深拷贝 + + 递归函数:一个函数内部调用自己,这个函数就是递归函数,==递归必须要加退出条件 return== + +~~~ javascript +const obj = { + uname: 'pink', + age: 18, + hobby: ['乒乓球','羽毛球'], + family: { + baby: '小pink' + } +} +// 深拷贝 +const o = {} +function deepCoppy(newObj,oldObj){ + for(let k in oldObj){ + //1. 判断属性值是否是数组类型(一定要先判断数组,在判断对象,因为数组也是对象) + if(oldObj[k] instanceof Array){ + // 是数组,就给要拷贝的对象的 hobby 属性先添加一个空数组 + newObj[k] = [] + // 递归,把要拷贝的属性 hobby,拷贝的值传入函数 + deepCopy(newObj[k],oldObj[k]) + //2. 判断属性值是否是对象类型 + }else if(oldObj[k] instanceof Object){ + // 是对象,就给要拷贝的对象的 family 属性先添加一个空对象 + newObj[k] = {} + // 递归,把要拷贝的属性 hobby,拷贝的值传入函数 + deepCopy(newObj[k],oldObj[k]) + }else{ + // k 属性值 uname oldObj[k] 属性值 18 + // newObj[k] === o.uname + newObj[k] = oldObj[k] + } + + } +} +// 调用函数 +deepCopy(o,obj) +~~~ + +2. 利用 js 库 lodash 里面的 **_.cloneDeep()** + +~~~ javascript +// 先引用 + + + const obj = { + uname: 'pink', + age: 18, + hobby: ['乒乓球','羽毛球'], + family: { + baby: '小pink' + } +} +const o = _.cloneDeep(obj) + +~~~ + +3. 利用 **JSON** 实现深拷贝 + +~~~ javascript +const obj = { + uname: 'pink', + age: 18, + hobby: ['乒乓球','羽毛球'], + family: { + baby: '小pink' + } +} +//1. 把要拷贝的对象转换为 JSON 字符串(直接存值) +//2. 再将 JSON 字符串 转成对象 +const o = JSON.parse(JSON.stringify(obj)) +~~~ + +**2. 异常处理** + + **throw 抛异常** + +- throw 抛出异常信息,程序也会终止执行 +- throw 后面跟的是错误提示信息 +- Error 对象配合 throw 使用,能够设置更详细的错误信息 + +~~~ javascript +function fn(x,y){ + if(!x || !y){ + // throw '没有传递参数进来' + throw new Error('没有传递参数进来') + } + return x + y +} +log(fn()) +~~~ + + **try / catch 捕获错误信息** + +~~~ javascript +

123

+function fn(){ + try { + //可能出错的代码,写在 try 里 + const p = document.querySelector('.p') + p.style.color = 'red' + } catch (err) { + // 拦截错误,浏览器提示出错信息,但是不中断程序执行 + log(err.message) + throw new Error('你看看,选择器错误了') + // 需要加 return 中断程序 + // return + } + finally { + // 不管程序有没有错误,都会执行这里面的代码 + alert('弹出警示框') + } + log(123) +} +fn() +~~~ + + **debugger** :代码断点标记 + +**3. 处理 this** + + **this 指向-普通函数** + +- 谁调用 this 就指向谁 +- 普通函数没有明确调用者时 this 指向 window + + **this 指向-箭头函数** + +- 箭头函数内不存在 this,沿用上一级的 +- 不适用:构造函数,原型函数,dom 事件函数 +- 适用:需要使用上层 this 的地方 + + **改变 this 指向** + +- **call (this指向谁 , 其他形参…)** + +~~~ javascript +const obj = { + uname: 'pink' +} +function fn(x,y) { + log(this) // 没有 call 指向 window,此时指向 obj + log(x + y) //3 +} +fn.call(obj,1,2) // 让 this 指向 obj 对象,可以传入参数 +~~~ + +- **apply (this指向谁 , [数组])** + +~~~ javascript +const obj = { + uname: 'pink' +} +function fn(x,y) { + log(this) // 没有 call 指向 window,此时指向 obj + log(x + y) //3 +} +fn.apply(obj, [1,2]) // 与 call() 的区别:实参一定要是数组,并且形参是根据数组的个数来接 +// 使用场景:求数组最大最小值 +const arr = [100,56,89] +const max = Math.max.apply(null,arr) +const min = Math.min.apply(null,[56,89,100]) +// 利用扩展运算符求 +log(Math.max(...arr)) +~~~ + +- **bind (this指向谁 , 其他形参…)** + + 上面两个都会调用函数,这个==不会调用函数,会返回一个新函数(修改后的)== + +~~~ html + + + +~~~ + +**4. 防抖(debounce)** + + 单位时间内,频繁触发事件,只执行最后一次 + + 假设:有一个定时器5秒钟执行一次,在未执行完前再次调用(会累加),此时利用防抖会先取消上一次,重新开始执行(王者荣耀的回城) + +方式一:lodash 里的 **_.debounce()** + +方式二:手写防抖函数 + +~~~ html +<- 案例:实现鼠标在盒子上滑动,盒子内的数字 ++ -> +
+ +~~~ + +**5. 节流(throttle)** + + 单位时间内,频繁触发,只执行一次() + + 例:王者荣耀技能冷却,期间不能使用该技能 + +~~~ html +<- 案例:实现鼠标在盒子上滑动,隔1秒 盒子内的数字 ++ -> +
+ +~~~ \ No newline at end of file -- Gitee