JavaScript - 基础+WebAPI(笔记)

news2024/11/28 4:40:55

前言:

  • 求关注😭
    image.png
  • 本篇文章主要记录以下几部分:
    • 基础:
      • 输入输出语法;
      • 数据类型;
      • 运算符;
      • 流程控制 - 分支语句;
      • 流程控制 - 循环语句;
      • 数组 - 基础;
      • 函数 - 基础;
      • 对象 - 基础;
    • Web API:
      • DOM;
      • DOM事件基础(事件监听、常用事件、事件对象);
      • DOM事件进阶(事件流、事件委托);
      • 日期对象;
      • 节点操作;
      • M端事件;
      • JS插件;
      • window对象;
      • 本地存储;
      • 正则表达式;

  • 以下部分请移步JavaScript - 进阶+高级(笔记):
    • 进阶:
      • 作用域;
      • 函数进阶(函数提升、函数参数、箭头函数);
      • 解构赋值;
      • 对象进阶(构造函数、实例成员、静态成员);
      • 内置构造函数(Object、Array、String、Number);
      • 编程思想;
      • 构造函数;
      • 原型
    • 高级:
      • 深浅拷贝;
      • 异常处理;
      • this指向;
      • 性能优化(防抖、节流);

壹、❗❗ JavaScript基础

  • HTML 表示网页的 结构
  • CSS 表示网页的 样式
  • JavaScript 表示网页的 行为
  • 浏览器内核 = 渲染引擎 + JS引擎
  • JavaScript的组成
    • ECMAScript — JS的基础语法
    • Web APIs
      • DOM — 操作文档流的属性和方法(文档对象模型
        • 是HTML文档的编程接口。它提供了对文档的结构化的表述,并定义了一种方式,可以在程序中对该结构进行访问,从而改变文档的结构、样式和内容。DOM将文档解析为一个由节点和对象(包含属性和方法)组成的结构集合。简言之,它会将 web页面和 程序 连接起来。进而操作网页的内容,实现各种功能和部分特效
      • BOM — 操作浏览器的属性和方法(浏览器对象模型
      • image-20220912145005712
  • JS的本质: 通过 JS 的语法,让 浏览器 发生变换,让 文档 发生变化。

一、JavaScript书写位置

  • 行内 JavaScript
  • 内部 JavaScript
  • 外部 JavaScript

二、输入输出语法

  • 小括号里面只要 不是纯数字变量 必须要用 引号包裹(单、双、反)
    alert()			        ---  警示框
    prompt()			---  浏览器弹出输出框,用户可以输入信息
    console.log()			---  控制台输出
    document.write()		---  在文档页面输出(识别标签)
    
  • 代码展示:
    alert('你好, js');
    prompt('JavaScript 基础');
    console.log('它~会魔法吧~');
    document.write('javascript我来');
    

三、字面量、变量、常量

3.1 字面量

  • 用来在计算机中描述 事 / 物
  • [ ] : 数组字面量
  • { } : 对象字面量
  • 数字字面量:数字
  • 字符字面量:字符串
  • 布尔字面量:布尔值

3.2 变量

  • 变量:用来 存储数据容器
  • 变量的本质:内存里的一块空间,用来 存储数据
  • 变量 必须 先声明 后使用
  • 变量的初始化: 声明变量赋值
  • 变量命名规则:变量名只能是 数字大小写字母美元符($)下划线组成(⚠ 不能以数字开头)
  • ⚠ 不能使用 name 作为变量名 (name会将 数字型 转为 字符型)
  • 声明 变量使用 let
  • 代码展示:
    // 声明变量
    
    // 声明变量不赋值
    let a   
    
    // 变量的初始化  ---  声明变量并赋值
    let age = 18	
    
    // 声明多个变量(用逗号隔开)--- 不推荐
    let a = 18, b = 'pink'   
    
    // 更新变量
    let age = 18
        age = 19
    console.log(age)   // 19
    
    // 用变量赋值
    let myFood = '香蕉'
    let youFood = myFood
    console.log(youFood)	  // 香蕉
    

3.2.1 var 和 let 的区别

  • var
    • 可以 先使用 再声明
    • var声明过的变量可以重复声明
    • 存在变量提升、没有块作用域等等。
  • let / const
    • 必须 先声明 后使用
    • 不能 声明 重复变量
    • 不存在变量提升
    • 使用了 let / const 声明的变量存在块作用域
    • const声明变量的时候必须初始化

3.3 常量

  • 声明常量使用 const
  • ⚠ 常量不允许重新赋值声明的时候必须赋值 (必须初始化)
    • 注意:
      const num = 10;
      num = 10;
      console.log(num);	// 报错 - 常量不允许重新赋值
      

四、❗❗ 数据类型

  • 1️⃣ 值类型 (基本数据类型)(6)
    • number — 数字型
    • string — 字符串型
    • boolean — 布尔型
    • undefined — 未定义型
    • null — 空类型
    • symbol (了解)
    • bigint
  • 2️⃣ 引用数据类型 (复杂数据类型)(3)
    • object — 对象
    • function – 函数
    • array — 数组

4.1 数字型 - number

  • 数字型 = number + NaN
  • Number 一切十进制表示的数字
Number.MAX_VALUE    // 数字中的最大值
Number.MIN_VALUE    // 数字中的最小值
Infinity	    // 无穷大
-Infinity	    // 无穷小
NaN		    // 非数值

isNaN(数据) 这个方法用来判定非数字,并且返回一个值,如果是数字返回 false,如果不是数字返回 true
image-20220623195831594 + `NaN` 代表一个计算错误,它是一个不正确的或者一个未定义的数学操作所得到的结果 + ⚠ **`NaN` 是 粘性 的。任何对 `NaN` 的操作都会返回 `NaN`**
console.log(2 - NaN)	   // NaN
console.log('粘性' + NaN)  // NaN
console.log(NaN === NaN)   // NaN

4.2 字符串型 - string

  • 用引号(单引号 / 双引号 / 反引号)包裹的都是字符串

4.2.1 字符串的长度

lengtn 属性
let strMsg = (`扶我起来,我还能干!`) 
console.log(strMsg.length)		// 显示 10

4.2.2 字符串的拼接

  • 多个字符串之间可以使用 + 进行拼接,其拼接方式为 字符串 + 任何类型 = 新的字符串
  • 拼接前会把与字符串相加的任何类型转成字符串,再拼接成一个新的字符串
  • +数字相加,字符相连

4.2.3 ❗❗ 模板字符串

  • 使用 反引号(``) 包裹
  • 模板字符串可以 嵌套变量
    • 代码展示:
      let myName = `邵秋华`
      let age = 22
      let str = `扶我起来,我还能干!`
      document.write(`我叫${myName},今年${age}岁了,我的座右铭是${str}`)
      

4.2.4 ❌ 转义字符

image-20220623200802891

4.3 布尔型 - boolean

  • 布尔类型 有 两个值truefalse,其中 true 表示 ,而 false 表示
  • 布尔型数字型 相加 的时候,true = 1false = 0
  • ❗ 除了 0''undefinednullNaNfalse 转换为布尔值后为 ,其余都为真

4.4 未定义类型 - undefined

  • 只声明变量不赋值 的情况下,变量的默认值为 undefined
    • undefined 这里本该有一个值,但是没有,就是 undefined
  • 数字 + undefined = NaN
  • 注意:
    • ⚠ 对 undefined 的任何操作都是NaN,除了拼接字符串
  • 出现情况:
    • 声明变量未赋值
    • 数组 里面 没有 某个 元素
    • 对象 里面 没有 某个 属性 或 方法
    • 函数
      • 形参多于实参(没有赋值的形参默认值是 undefined)
      • 函数未指定返回值(没有 return 关键字)
console.log(undefind + 1)	    // NaN
condsole.log(undefined + 'purple')  // undefinedpurple
console.log(typeof(undefined))	    //undefined

4.5 空类型 - Null

  • Null 这里有一个值,有一个空值
  • ✅参与 数学运算 的时候,null = 0
console.log(null + 1)	        // 1
console.log(null + 'purple')    // nullpurple
console.log(typeof(null))	// object
image-20220623194305096

4.6 null 和 undefined 区别:

  • undefined 表示 声明了一个变量,但是没有赋值
    • let num
      console.log(undefined + 1)	// NaN
      
  • null 表示 声明了一个变量 并且 赋值了,但是内容为空
    • let num = null
      console.log(null + 1)	// 1
      
  • ✅注意:
    • nullundefined 值相等,数据类型不相等
    console.log(null == undefined)	// true
    

4.7 检测数据类型

  • 1️⃣ 作为运算符:typeof 数据
  • 以 字符串 的形式 给你变量的数据类型
  • ⚠ 使用 typeof 检测 错误类型 为 undefined 的代码不会报错,检测结果是 undefined
  • 2️⃣ 函数形式:typeof(数据)(推荐使用)
    • 以字符串的形式给你变量的数据类型
    • 先运算小括号里面结果,然后去检测结果的数据类型
    • 代码展示:
      let num = 10;
      console.log(typeof num);	  // number
      let str = 'purple';
      console.log(typeof str);	  //string
      let flag = true;
      console.log(typeof flag);     //boolean
      let i = undefined;
      console.log(typeof i);	  //undefined
      let timer = null;
      console.log(typeof timer);	  //object
      // 注意
      console.log(typeof (a));	  // undefined
      
  • 3️⃣ instanceof
    • 用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。
    • 返回值:布尔值(true / false)
  • 4️⃣ 究极方法: Object.prototype.toString()
    • 可以通过 toString() 来获取每个对象的类型。为了每个对象都能通过 Object.prototype.toString() 的检测,需要以 Function.prototype.call()Function.prototype.apply() 的形式来调用,传递要检查的对象作为第一个参数。
    • 返回值:[ object type ]
    • 代码展示:
      // 引用数据类型
      const obj = {uname: '迪迦', age: 22};
      console.log(Object.prototype.toString.call(obj));	// [object Object]
      const arr = [1, 2, 3];
      console.log(Object.prototype.toString.call(arr));	// [object Array]
      const fn = function () { console.log(1) };
      console.log(Object.prototype.toString.call(fn));	// [object Function]
      
      // 基本数据类型
      console.log(Object.prototype.toString.call(123));	// [object Number]
      console.log(Object.prototype.toString.call('123'));		// [object String]
      console.log(Object.prototype.toString.call(false) );	// [object Boolean]
      console.log(Object.prototype.toString.call(undefined));	// [object Undefined]
      console.log(Object.prototype.toString.call(null));		// [object Null]
      

4.8 数据类型转换

4.8.1 转数字

  • 1️⃣ parseInt(string) 可以把 字符串型 转换为 整数型不识别小数点
    • 第一个字符开始 取第一个整数,如果取不到就是NaN
    • ⚠ 转换的字符开头如果不是数字,就是NaN
    • 代码展示:
      console.log(parseInt('3.14'))	  //3(取整数位)
      console.log(parseInt('3.99'))	  //3(取整数位)
      console.log(parseInt('120px'))        //120 (自动去除单位,前面必须是数字)
      console.log((parseInt'rem120px'))     //NaN
      console.log(parseInt(true))		  //NaN
      console.log(parseInt(null));	  // NaN
      
  • 2️⃣ parseFloat(string) 可以把 字符串型 转换为 浮点型识别小数点
    • 第一个字符开始取第一个小数,如果取不到就是NaN
    • ⚠ 转换的字符开头如果不是数字,就是NaN
    • 代码展示:
      console.log(parseFloat('3.14'));	  //3.14
      console.log(parseFloat('3.99'));	  //3.99
      console.log(parseFloat('120px'));     //120 (自动去除单位,前面必须是数字)
      console.log(parseFloat('rem120px'));  //NaN
      console.log(parseFloat(true))	  //NaN
      console.log(parseFloat(null));	  // NaN
      
    • ⚠ 注意:
      parseInt 和 parseFloat 单词的大小写
      
  • 3️⃣ Number(string) 强制转换
    • 转换的数据中不能包含非数字,如果有就是NaN
    • 识别小数点
    • 代码展示:
      let num = '123';
      console.log(Number(num));			  //123
      console.log(Number('12')); 		 	//12
      console.log(NUmber('123.123');	       // 123.123
      console.log(Number('123abc');		//NaN
      console.log(Number(null));			// 0
      console.log(Number(true));			// 1
      console.log(Number(false));			// 0
      
  • 4️⃣ 利用了算术运算 **+(正号) - * / % ** 隐式转换
    • 代码展示:
      console.log('12' - 0);	  //12	(先将 '12' 转换成数字型在进行减)
      console.log('123' - '120');		//3
      console.lof('123' * 1);		  //123
      console.log(+'123')			//123
      + 号作为正号解析可以转换成数字型(单用)
      
      let year = prompt('请输入您的出生年份:');
      //let age = 2022 - year;
      alert('您今年:' + (2022 - year) + '岁了');
      
    • 注意:
      • 隐式转换是我们在进行算数运算的时候,JS 自动转换了数据类型
      • 代码展示:
        let num1 = prompt('请输入第一个数据:');	//得到的num1是字符型的
        let num2 = prompt('请输入第二个数据:');	//得到的num2是字符型的
        let result = parseInt(num1) + parseInt(num2);
        alert(parseInt(num1) + '+' + parseInt(num2) + '=' +  result);
        
        /*
        let num1 = +prompt('请输入第一个数据:');	
        let num2 = +prompt('请输入第二个数据:');	
        let result = num1 + parseInt(num2);
        */
        
image-20220624101901837
  • 注意:
    • 有字符串的加法 ‘’ + 1,结果是 ‘1’
    • 减法 只能用于数字,它会使 空字符串 ‘’ 转换为 0
    • null 经过 数字转换 之后会变为 0
      • parseInt(null);		// NaN
        parseFloat(null);	// NaN
        Number(null);		// 0
        
    • undefined 经过 数字转换 之后会变成 NaN
    • undefined 做任何操作都是 NaN 除了拼接字符串
    null == undefined	// true 值都是空
    null === undefined  // false 数据类型不一样
    
    image-20220727173543226

4.8.2 转字符串

  • 1️⃣ String(数据)
    • 返回值:转换好的数据
    • 代码展示:
      console.log(String(123))		// '123'
      
  • 2️⃣ 数据.toString()
    • 返回值:转换好的数据
    • ⚠ **注意:**需要 配合 变量 使用、
    • 代码展示:
      let num = 123
      console.log(num.toString())  // '123'
      
  • 3️⃣ +(加号)
    • 字符串的拼接
    • 代码展示:
      console.log(123 + '')				// '123'
      
image-20220623205607781
toString()String()  使用方式不一样。
三种转换方式,我们更喜欢用第三种加号拼接字符串转换方式, 这一种方式也称之为隐式转换。

4.8.3 转布尔

  • Boolean(数据)
    • 返回值:转换好的数据
    • ⚠ 注意:代表 、**否定的值 **会被 转换成 false
      • ‘’、 0、 NaN、 null、 undefined、 false
    • 代码展示:
      console.log(Boolean(''))		// false
      console.log(Boolean(0))		// false
      console.log(Boolean(NaN))		// false
      console.log(Boolean(null))		// false
      console.log(Boolean(undefined))	// false
      console.log(Boolean(false))		// false
      
      注意:
      // 两个等号值比较 值
      // null 和 undefined 都是空
      console.log(null == undefined)	// true
      

五、运算符

5.1 算术运算符

image-20220624103954490 + ⚠ **注意:** + 取余前面的数比后面的小,余数就是前面的数

5.2 递增递减运算符

5.2.1 前置++

  • 先自加,后返回值
  • 先自加,后运算(++在前 先加
let  num = 10;
alert(++num + 10);   // 21

5.2.2 后置++

  • 先原值运算,后自加(++在后 后加
  • 先表达式返回原值,后面变量再自加1
let  num = 10;
alert(10 + num++);  // 20
  • **注意:**前置++ 和 后置++ 单独书写没有差别

5.2.3 前置–

先自减,后运算(先已后人)
let  num = 10;
alert(--num + 10);   // 19

5.2.4 后置–

先原值运算,后自减(先人后己) 
let  num = 10;
alert(10 + num--);  // 20
let a = 10;
++a;              // ++a = 11  a = 11
let b = ++a + 2;  // a = 12    ++a = 12
console.log(b);   // 14

let c = 10;
c++;		  // c++ = 11  c = 11
let d = c++ + 2;  // c++ = 11  c = 12
console.log(d);	  // 13

let e = 10;
let  f = e++ + ++e;
// e++ = 10   e = 11
// e = 12    ++e = 12
console.log(f);	   // 22

5.3 比较运算符

image-20220624104610215
  • 注意:
    • 比较运算符有隐式转换
    • console.log(2 == '2')		// true
      
  • 特殊说明:
    • 如果是数字和“其他值”的比较,则其他值会自动转换成数字去比较
    • 涉及到“NaN”都是false
    • 如果是”字符串“和“字符串”比较,则会比较每一个字符的ASCII码
    • 如果是布尔值参与比较,布尔值会自动转换成数字0和1
    • 数字只有0是假,其余为真
    • 字符串只有’'(空字符串)是假,其余都为真

5.4 ❗ 逻辑运算符

image-20220707185825834
  • 1️⃣ && 与 有 一个 是 false ,得到的 结果 就是 false ;只有 两侧 都是 true 的时候,才可以到的 true
  • 2️⃣ || 或 有一个 是 true ,得到的结果就是 true ;只有 两侧 都是 false 的时候,才得到 false
  • 3️⃣ ! 非 取反(双取反可以转布尔)
  • 注意: 逻辑运算符 优先级: ! > && > ||

5.4.1 短路运算(逻辑中断)

  • 短路运算的原理:当有多个表达式(值)时,左边的表达式值可以确定结果时,就不再继续运算右边的表达式的值;
  • 1️⃣ 逻辑与-语法:(一假则假
    • 表达式1 && 表达式2
      	 如果 表达式1的值 为 真,则返回 表达式2
         如果 表达式1的值 为 假,则返回 表达式1 (后面的表达式不再执行)
      	 两侧都为真,返回第二个
      
  • 2️⃣ 逻辑或-语法: (一真则真
    • 表达式1 || 表达式2
      	 如果 表达式1的值 为 真,则返回 表达式1 (后面的表达式不再执行)
         如果 表达式1的值 为 假,则返回 表达式2 
         两侧都为真返回第一个
      

5.5 赋值运算符

image-20220624104834906

5.6 ❗ 运算符优先级

  • 一元运算符逻辑非 优先级最高
  • 逻辑与逻辑或 优先级
    image-20220624105604315
  • console.log( 4 >= 6 || '人' != '阿凡达' && !(12 * 2 == 144) && true)  // true
    let num = 10
    console.log( 5 == num / 2 && (2 + 2 * num).toString() ===22)		// true
    let a = 3 > 5 && 2 < 7 && 3 == 4 
    console.log(a)  		// false
    let b = 3 <= 4 || 3 > 1 || 3 != 2 
    console.log(b) 		// true
    let c = 2 === "2" 
    console.log(c)  		// false
    let d = !c || b && a 
    console.log(d)		// true
    

六、流程控制 - 分支语句

  • 表达式和语句的区别:
    • 表达式:表达式可被求值,可以写在赋值语句的右侧(运算符和数据组成的式子)
    • 语句:不一定有值(可以被执行的代码)

6.1 if 语句

  • 条件为 true 的时候,大括号里面的代码才会执行

  • 小括号里的结果若不是布尔类型时,会发生隐式转换转为布尔类型

  • ⚠ if分支语句,如果前面的条件被满足,后面的代码就不执行了

  • if (条件) {
      满足条件要执行的代码
    }
    
  • if (条件) {
      满足条件要执行的代码
    } else {
      条件不满足时要执行的代码
    }
    
    eg:
    // 能被4整除但不能被100整除,或者被400整除的年份是闰年,否则都是平年
    let year = +prompt('请输入年份:')
    if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) {
      alert(`&{year}是闰年`)
    } else {
      alert(`&{year}是平年`)
    }
    
  • if (条件表达式1) {
      满足条件1要执行的代码
    } else if (条件表达式2) {
      满足条件2要执行的代码
    } else if (条件表达式n) { 
      满足条件n要执行的代码
    } else {
      所有条件都不满足时要执行的代码
    }
    

6.2 三元运算符

  • 语法结构:
    条件表达式 ? 表达式1 : 表达式2
    
  • 执行思路:
    • 如果 条件表达式 结果 为真,则 返回 表达式1 的值,如果 条件表达式 结果 为假,则 返回 表达式2 的值
  • 代码展示:
    let time = prompt('请您输入一个 0 ~ 59 之间的一个数字')
    // 三元表达式 表达式 ? 表达式1 :表达式2 
    let result = time < 10 ? '0' + time : time // 把返回值赋值给一个变量
    alert(result)
    
    /* 如果输入的数字小于10,就在该数字前面加一个0,否则原样输出该数字 */
    let num = prompt('请输入数字:')
    let result = num < 10 ? '0' + num : num
    alert(result)
    

6.3 switch 语句

  • 表达式有一个返回值,**返回值 **会和 value 做匹配(必须是 全等 的关系),如果匹配上了就执行对应的语句 ,如果都匹配不上就执行default里的语句
  • 语法:
    switch ( 表达式 ) {
    	case value1:
    	满足value1执行的代码
    	break
    	case value2:
    	满足value2执行的代码
    	break
    	default:
    	所有条件都不满足时要执行的代码
    }
    
  • 注意:
    • 每一个 case表达式 必须是 ===数据类型 都相等) 才叫满足
    • switch 语句,只能判断一些准确的值,不能判断范围
    • 实际开发过程中 表达式 我们经常 写成 变量
    • 代码展示:
      let num1 = +prompt('请输入第一个数字:')
      let sp = prompt('请输入 + - / * 其中一个:')
      let num2 = +prompt('请输入第二个数字:')
      
      switch (sp) {
        case '+':
          let add = num1 + num2
          alert(`${num1} + ${num2} = ${add}`)
          break
        case '-':
          let dif = num1 - num2
          alert(`${num1} - ${num2} = ${dif}`)
          break
        case '*':
          let bus = num1 * num2
          alert(`${num1} x ${num2} = ${bus}`)
          break
        case '/':
          let pro = num1 / num2
          alert(`${num1} ÷ ${num2} = ${pro}`)
          break
        default:
          alert('请输入正确的运算符')
          break
      }
      

七、流程控制 - 循环语句

7.1 循环成立的条件

  • 初始值 作为循环的开始
  • 条件判断 决定要不要继续循环
  • 要重复执行的代码
  • 改变初始值 为了让循环有结束

7.2 ❗ for 循环

  • 语法结构:
    for (初始化变量; 条件表达式; 操作表达式) {
        循环体
    }
    
  • 初始化变量:通常被用于初始化一个计数器,这个变量帮我们来记录次数。
  • 条件表达式:用于确定每一次循环是否能被执行。如果结果是 true 就继续循环,否则退出循环。(终止条件)
  • 操作表达式:每次循环的最后都要执行的表达式。通常被用于更新或者递增计数器变量。当然,递减变量也是可以的。(递增或者递减)
  • 代码展示:
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
    </head>
    
    <body>
    
    </body>
    
    <script>
      // 求1-100之间所有数字的和
      let  sum = 0;
      let average = 0;
      for (let i = 1; i<= 100; i++) {
          sum += i
      }
      average = sum / 100;
      console.log('1-100之间所有数字的和为:' + average); 
    
      // 求1-100之间所有偶数的和和奇数的和
      let even = 0;
      let odd = 0;
      for (i = 1; i <= 100; i++) {
        // 第一种
        if (i % 2 == 0) {
          even = even + i;
        } else {
          odd += i;
        }
        
        //第二种
        if (i % 2 == 0) {
          even = even + i;
        }
        odd = sum - even;
      }
      console.log('1-100之间所有偶数的和为:' + even + '\n' + '1-100之间所有奇数的和为:' + odd);
    
      // 求1-100之间所有能被3整除的数字的和
      let odd_num = 0;
      for (let i = 1; i <= 100; i++) {
          if (i % 3 == 0) {
              odd_num = odd_num + i;
          }
      }
      console.log('1-100之间所有能被3整除的数字的和为:' + odd_num);
      
      //弹出输入框,输入一共有n个学生,然后弹出n个输入框,输入每个学生的成绩,最后输出总成绩和平均成绩
      let frequency = prompt('请输入有多少个学生:');
      let score = 0;
      for (let i = 1; i <= frequency; i++) {
          let a = prompt('请输入第' + i + '个同学的成绩:');
        // 从 prompt 获取到的数据是 String 类型的,不能直接和数字进行相加
          score = score + parseFloat(a);
       }
      alert('该班总成绩是:' + score);
      alert('该班平均成绩是:' + (score / frequency));
    
      //一行打印五个星星
      let str = ' ';
      for (let i = 1; i <=5; i++) {
              str = str + '⭐';
      }
      console.log(str);
    </script>
    </html>
    
    image-20220628205809445
image-20220628213008738

7.3 ❗ 双重for循环

  • //打印n行m列的星星
    let rows = +prompt('请输入需要打印几行的星星:');
    let cols = +prompt('请输入需要打印几列的星星:');
    let str = '';
    for (let i = 1; i <=rows; i++) {
      for (let j = 1; j <= cols; j++) {
        str +=  '⭐';
      }
      str += '\n';
    }
    console.log(str);
    
image-20220630110759649
  • 冒泡排序:
    // 外层for循环:控制已经排序好的元素的个数
    // 内层for循环:控制每排序好一个元素需要比较几次
    const arr = [1, 7, 3, 9, 5, 2, 6, 4, 8];
    for (let i = 0; i < arr.length - 1; i++) {
      for (let j = 0; j < arr.length - i - 1; j++) {
        if (arr[j] > arr[j + 1]) {
          let temp = arr[j + 1];
          arr[j + 1] = arr[j];
          arr[j] = temp;
        }
      }
    }
    console.log(arr);
    

7.4 while循环

  • 循环三要素:
    • 变量初始值
    • 终止条件
    • 变量变化量
  • 语法:
    let n = 1
       while ( 循环条件 ) {
           重复执行的代码
           n++
       }
    

7.5 ❗ continue 和 break

  • continue
  • 退出本次循环,继续下一次循环
  • 一般用于排除或者跳过某一个选项的时候
  • continue 在循环节构中用来跳过本次循环中剩余的代码,并且在条件求值为真的时开始下一次循环。
  • 不能省略 continue 后面的分号(导致胡乱)
  • continue 后面 的 代码 不会 再 执行
  • break
  • 退出整个循环(结束循环)
  • 一般用于结果已经得到,后续的循环不需要的时候
  • 在一些计算机语言中 break 是保留字,其作用大多数情况下是终止上一层循环。

7.6 JS标记语法

  • JS标记语法
    here:
    for (let i = 1; i <= 5; i++) {
      for (let j = 1; j <= 3; j++) {
        if (i === 3 && j === 2) {
          console.log('看到半条虫子')
          break here
        }
        console.log('吃的第 ' + i + ' 个包子得第 ' + j + ' 口')
      }
      console.log('=================')
    }
    

八、❗❗ 数组 - 基础

  • 一种 有序 的数据集合

8.1 创建数组

8.1.1 字面量创建

let 数组名 = [数据1, 数据2,, 数据n]
let arr = ['name', 'Jack', 'age', 20, 'gender', '男'] 

8.1.2 内置构造函数创建

//没有参数表示空数组
let arr = new Array()  

//一个参数表示数组的长度
let arr = new Array(100) 

//多个参数表示都是数组里面的数据,没有表示长度的参数
let arr = new Array(10, 20, 30) 
arr.length = 2				//删除最后一个
arr.length = 5				//后面的两个用空补齐
console.log(arr[2])		//读取里面的额第三个数据

8.2 ❗❗ 遍历数组

能够获取数组里面的每个元素

8.2.1 for

  • 格式:
    for (let i = 0; i < 数组名.length; i++) {
      // 执行的操作
      // console.log(数组名[i])
    }
    

8.2.2 forEach

  • 取代 for 循环
  • 语法:
    数组.forEach(function (item, index, arr) {  } )
      -> item :数组里面的每一项
      -> index :数组里面每一项的索引
      -> arr : 原始数组
    
  • 没有 返回值
  • forEach中的 return 等同于 for循环的 continue
  • 终止forEach循环:try - catch
    try {
      [1, 2, 0, 3].forEach(item => {
        console.log(item)
        if (item === 1) {
          console.log(item)
          throw Error()
        }
      })
    } catch (error) {
      console.log('终止循环')
    }
    
    // 打印结果
    // 1
    // 1
    // z
    

8.2.3 for of

  • 遍历 可迭代 的数据:数组,伪数组,字符串
  • 遍历的是数组、伪数组、字符串的值
  • 语法:
    for (let item of arr) {
      console.log(item)		//  item -> 数据里面的每一项
    }
    

8.3 数组的增删查改

8.3.1 增

  • 1️⃣✔数组.push() 方法:将 一个或多个元素 追加 **到 数组末尾 ,并 返回 追加元素后数组长度
    • 语法:数组.push(数据1, 数据2, … ,数据n)
    • 返回值: 追加元素后数组的长度
    • 改变原始数组
  • 2️⃣ 数组.unshift() 方法:将 一个或多个元素 插入数组开头,并 返回 插入元素后数组长度
    • 语法:数组.unshift(数据1, 数据2, …, 数据n)
    • 返回值: 插入元素后数组的长度
    • 改变原始数组
  • 见代码展示

8.3.2 删

  • 1️⃣ 数组.pop() 方法:从数组中 删除 最后一个 元素
    • 语法:数组.pop()
    • 返回值: 被删除的元素
    • ⚠改变原始数组
  • 2️⃣ 数组.shift() 方法:从数组中 删除 第一个元素
    • 语法:数组.shift()
    • 返回值: 被删除的元素
    • 改变原始数组
  • 3️⃣ ✔数组.splice(start, deleteCount) 方法:删除 数组 里 指定的元素
    • 语法:数组.splice(开始索引,删除几个)
      • ⚠🔺 注意:包含开始索引 对应元素
      • deleteCount:表示要移除的数组元素个数(如果 省略默认指定的起始位置 删除到最后
    • 返回值: 新数组(将删除的元素放到这个新数组里面)
    • 改变原始数组
  • 见代码展示

8.3.3 查

  • 见代码展示

8.3.4 改

  • 见代码展示

代码展示:

<script>
  let arr = ['pink', 'red'];
  // 增加
    // 方案一:数组.push()方法
        语法:arr.push(元素1, 元素2,, 元素n);
        追加数组 的同时 有一个 返回值 是 追加以后 的 数组长度
        console.log(arr.push('green', 'hotpink', 'deeppink'));	// 5
        console.log(arr); 
	// ['pink', 'red', 'green', 'hotpink', 'deeppink']
		
    // 方案二:数组.unshift()方法
        语法:arr.unshift(元素1, 元素2,, 元素n);
        console.log(arr.push('green', 'hotpink', 'deeppink'));	// 5
        console.log(arr);
        // ['green', 'hotpink', 'deeppink', 'pink', 'red']
	
 // 删除
    // 方案一:数组.pop()
        console.log(arr.pop());		// green
    // 方案二:数组.shift()
        console.log(arr.shift());	// red
    // 方案三:数组.splice(起始位置的索引, 删除几个元素)
        // 从索引号0的位置开始,删除两个元素
        console.log(arr.splice(0, 2));	// ['hotpink', 'deeppink']

 // 查询 --- 利用数组的索引进行查找
        console.log(arr[0]);	// pink

 // 修改 --- 利用 对数组进行遍历,然后和字符串拼接,重新赋值给数组里的元素
    // 方案一:
    arr[0] = 'blue';
    arr[1] = 'purple';

    //方案二:
    for (let i = 0; i < arr.length; i++) {
        arr[i] += '老师';
    }
    console.log(arr)
</script>

九、❗❗ 函数

  • 函数:执行特定任务的代码块

9.1 函数的声明和使用

9.1.1 函数的声明

  • 函数命名规范:
    • 和变量命名基本一致
    • 小驼峰式命名法
    • ⚠ 前缀应该为动词
      • can		---		判断是否可执行某个动作
        has		---		判断是否含义有某个值
        is		---		判断是否为某个值
        get		---             获取某个值
        set		---		设置某个值
        load	        ---		加载某些数据
        
  • 1️⃣ 具名函数
    • 语法
      function 函数名() {
        函数体
      }
      
    • ⚠ 注意:可以 后声明先调用 ,也可以 先声明后调用
  • 2️⃣ 匿名函数
    • 使用方式:
      • 函数表达式:
        • 语法:
          let 函数名 = function () {
              // 函数体
          }
          
      • 立即执行函数:
        • 语法:
          !(function (实参) { 函数体 })(实参);
          !(function (实参) { 函数体 } (实参));
          
        • 注意: 立即执行函数 末尾 必须加 分号
    • 注意:
      • 函数名() — 表示调用这个函数
      • 函数名 — 表示一个变量,代表这个函数
  • 代码展示:
    function getSum() {
      let sum = 0
      for (let i =  1; i <= 100; i++) {
        sum += sum
      }
      document.write(sum)
    }
    

9.1.2 函数的使用

  • 函数的调用:
    • 函数名()
      
  • 注意: 声明的函数 必须 调用 才会真正执行,使用 () 调用函数
  • 函数 一次声明 可以 多次调用 ,每一次函数调用函数体里面的代码会重新执行一次
    • 代码展示:
      function getSum() {
        let sum = 0
        for (let i =  1; i <= 100; i++) {
          sum += sum
        }
        document.write(sum)
      }
      getSum()	// sum = 5050
      

9.1.3 函数传参

  • 声明语法:
    • function 函数名(参数列表) {
        函数体
      }
      
    • 传入数据列表
    • 声明这个函数需要传入几个数据
    • 多个参数之间用 逗号 隔开
    • 代码展示:
      function getSum(start, end) {
        // 形参 - 形式上的参数
        let sum = 0
        for (let i =  start; i <= end; i++) {
          sum += sum
        }
        document.write(sum)
      }
      
  • 调用语法:
    • 函数名(传递的参数列表)
      
    • 代码展示:
      getSum(10, 20)	// sum = 33
      // 实参 - 实际的参数
      
    • 形参
      • 形式上的参数 — 写在 函数声明阶段小括号
      • 本质:就是在函数内部声明的变量(局部变量)
      • 作用:接受实参传递的参数
      • 如果既没有实参传递,也没有设置默认值,就是 undefined
    • 实参
      • 实际上的参数 — 写在 **函数调用阶段 **的 **小括号 **里
      • 实参 可以是 变量
      • 作用:给形参赋值
  • 参数默认值:
    • 在调用的过程中,如果有参数传递过来,就用传递过来的;如果没有参数传递过来就用默认的
    • ⚠ **注意:**若没设置默认值,默认就是 undefined
    • 代码展示:
      function getSum(x = 0, y = 0) {
        // 小括号里写了就不用写
        // 推荐用逻辑中断
        // x = x || 0
        // y = y || 0
        document.write(x + y)
      }
      
      getSum()	// 0
      getSum(1, 2)   // 3
      

9.1.4 函数的返回值:

  • 语法:返回给调用者(当调用某个函数,这个函数会返回一个结果出来)
    return 要返回的数据
    
  • 注意:
    • 函数体 中使用 return 关键字能 将内部的执行结果 交给 函数外部 使用
    • 所以 return 后面的数据不要换行写
      • ⚠ return 和 要返回的数据不能换行写(模板字符串、函数除外)
    • 一个函数只能有一个return(因为第一个return后面的代码就不执行了)
    • 如果 函数 没有指定 return,这种情况函数 默认返回值undefined
    • 函数如果有 多个返回值 ,用 中括号包裹中间逗号隔开返回的是一个新数组
  • 代码展示:
    • function fn() {
          return 20   // 把 结果(20) 返回给 fn
      }
      fn()  // 相当于执行了 fn() = 20	(fn()是函数的调用者)
      console.log(fn())	// 20
      
      // 求两个数的最大值
      function getMax(x = 0, y = 0) {
        return x > y ? x : y
      }
      
      getMax(65, 99)	// 99
      let max = getMax(65, 99)
      console.log(max)	
      
    • 求数组里面的最大值和最小值
    • 代码展示:
      // 声明一个 getArrValue函数
      function getArrValue(arr = []) {
        let max = arr[0]
        let min = arr[0]
        //遍历数组
        for (let i = 0; i < arr.length; i++) {
          // 最大值
          if (max < arr[i]) {
            max = arr[i]
          }
      		
          // 最小值
          if (min > arr[i]) {
            min = arr[i]
          }
        }
      	
        // return 返回多个值写法
        return [max, min]
      }
      
      let newArrr = getArrValue([23, 56, 32, 198, 0, 5, -98])
      
      console.log(`数组中的最大值是:&{newArr[0]}`)		// 198
      console.log(`数组中的最小值是:&{newArr[1]}`)		// -98
      
      • 时间转换 + 补0
      • 代码展示:
        function getTime(t = 0) {
          let second = parseInt(t % 60)
          let minute = parseInt(t / 60 % 60)
          let hour = parseInt(t / 60 / 60 % 24)
        
          // if条件分支语句
          /*  if (second < 10) {
                  second = '0' + second
              }
        
              if (minute < 10) {
                  minute = '0' + minute
              }
        
              if (hour < 10) {
                      hour = '0' + hour
              } */
        
          // 三元表达式
          second < 10 ? second = '0' + second : second
          minute < 10 ? minute = '0' + minute : minute
          hour < 10 ? hour = '0' + hour : hour
        
          return `${t}秒 = ${hour}小时${minute}分钟${second}`
        }
        
        let str = getTime(+prompt('请输入秒数:'))	// 1000
        document.write(str)		// 1000秒 = 00小时16分钟40秒
        
  • 函数注意点:
    • 两个函数名相同的函数,后面的会覆盖前面的
    • 两个函数体相同的匿名函数不是同一个函数
    • 传递参数
      • 形参过多会自动填上 undefined
      • 实参多于形参,剩余的实参不参与运算
      • 实参少于形参,多于的形参使用默认值 undefined
    • 函数一旦碰到 return 就不会往下执行,函数的结束用 return
  • break 和 return 的区别:
    • break结束 的是 循环 和 switch
    • return结束 的是 函数for循环

9.2 作用域基础

作用域: 变量的 可用性范围 就是 作用域 (提高程序逻辑的局部性)

9.2.1 全局作用域

  • 全局有效
  • 作用与所有代码执行的环境(整个script标签内部)或者一个独立的js文件

9.2.2 局部作用域

  • 局部有效
  • 作用与函数内的 代码环境,就是局部作用域。因为跟函数有关,所以也称为函数作用域

9.2.3 特殊

  • 如果函数内部,变量没有声明,直接赋值。也当全局变量看。不推荐
    • 代码展示:
      function fn() {
        num = 10	// 全局变量来看
      }
      
      fn()									
      console.log(num)	// 10
      
  • 函数内部的 形参 可以看作是 局部变量
    • 代码展示:
      function fun(x, y) {
        // 形参可以看做是函数的局部变量
        console.log(x)	// 1
      }
      fun(1, 2)				
      console.log(x)	// x is not defined (报错)
      

9.3 变量的访问原则

  • 只要是代码,就至少有一个作用域
  • 写在函数内部的局部作用域
  • 如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域
  • 访问原则就近原则):在能够访问到到的情况下 先局部,局部没有 再找全局 (由内向外)
    • 代码展示:

      functin f1 () {
        let num = 123
        function f2 () {
          console.log(num)	//   123
        }
        f2()
      }
      let num = 456
      f1()						
      
      function f1() {
        let num = 123
        function f2() {
          let num = 0
          console.log(num)	//  0
        }
        f2()
      }
      let num = 456
      f1()				
      
      let a = 1
      function fn1() {
        let a = 2
        let b = '22'
        function fn2() {
          let a = 3
          fn3()
          function f3() {
            let a = 4
            console.log(a)	//  a的值 = 4
            console.log(b)	//  b的值 = '22'
          }
        }
      }
      fn1()
      

9.4 匿名函数

  • 没有名字的函数,无法直接使用
  • 使用方式: 函数表达式 / 立即执行函数
    • 1️⃣ 函数表达式:
      • 函数表达式:将匿名函数赋值给一个变量,并且通过变量名称进行调用
      • 语法:
        let 变量名 = function () {
          // 函数体
        }
        
      • 调用:变量名()
      • 代码展示:
        let fn = function () {
          console.log('我是函数表达式')
        }
        fn()  //  我是函数表达式
        
      • ⚠🔺 注意: 函数表达式 必须 声明 调用
        • 因为变量必须先声明后使用
    • 2️⃣ 🔻**立即执行函数:**避免全局变量的污染(防止变量污染(冲突)
      • 函数声明后立即执行,并且执行完一次后被释放
      • 语法:
        // 写法一:
        (函数)();		
        
        // 写法二:
        (函数 ());	
        
      • ⚠ 立即执行函数 必须 分号
      • 立即执行函数可以传递参数
      • 先写两个小括号,前面的小括号写函数
      • 可以给匿名函数添加函数名
      • 最后面的小括号相当于调用函数
        • 代码展示:
          (function () {
            console.log('立即执行函数')
          })();
          // 保存之后会在控制台立即打印 '立即执行函数'
          
          // 第一种写法:
          (function () {
              console.log('立即执行函数第一种写法');
          })();
          
          (function (x, y) {	// (x, y) --->   形参
            console.log(x, y);	// x = 5; y = 9
          })(5, 9);		// (5, 9) --->   实参
          
          
          // 第二种写法:
          (function () {
              console.log('立即执行函数第二种写法');
          } ());
          
          (function (x, y) {	// (x, y) --->   形参
            console.log(x, y);	// x = 5, y = 9
          } (5, 9));	// (5, 9) --->   实参
          

9.5 具名函数 和 匿名函数 的区别

  • 具名函数:
    • 可以 先调用 后声明,也可以 先声明 后调用
    • 具名函数 的 调用 可以 写在 任意位置
  • 匿名函数
    • 函数表达式必须 先声明函数表达式 后调用
    • 匿名函数 的 调用 必须写在 声明函数 的 后面

9.6 函数中的逻辑中断

  • 函数的默认值
    • 方案一:(赋值)
      function fn(x = 0, y = 0) {
        x = x
        y = y
        console.log(x, y)
      }
      fn(1, 2)	// x = 1, y = 2
      fn()	// x = 0, y = 0
      
    • 方案二:(逻辑中断)(推荐)
      function fn(x, y) {
        x = x || 0
        y = y || 0
        console.log(x, y)
      }
      fn(1, 2)	// x = 1, y = 2
      fn()	// x = 0, y = 0
      

十、❗❗ 对象 - 基础

  • 对象 = 属性 + 方法

10.1 对象 - object

  • 对象是一种复杂数据类型
  • 一种 无序 的数据集合(不可迭代)

10.2 使用对象

10.2.1 声明对象

  • 语法:
    • let 对象名 = {}
    • let 对象名 = new Object()
    let obj = {}		// 声明了一个obj的对象
    let obj = new Object();
    
  • 组成:属性 + 方法
    let 对象名 = {
    	属性名: 属性值,
      方法名: 函数
    }
    
    eg:
      let obj = {
       uname: 'pink老师',
       age : 18,
       gender: '男'
     }
      console.log(obj)
      // {uname: 'pink老师', age: 18, gender: '男'}
    
    • 属性都是 成对 出现的,包括 属性名属性值 ,它们之间使用英文 : 分隔
    • 对象属性没有顺序
    • 多个属性之间使用英文 , 分隔
    • 属性就是依附在对象上的变量(外面变量对象内属性
    • ⚠ 属性名可以使用 " "’ ’ ,一般情况下省略,除非名称遇到特殊符号如 空格 、 中划线 等
      • 属性名 不能 使用 反引号

10.2.2 增删查改

  • 1️⃣
    • 语法:
      • 对象名.属性名
      • 对象名[‘属性名’] (🔺 属性名 必须 引号
        • ⚠ 如果属性名存放在一个 变量 里面,只能使用 数组关联语法
    • 代码展示:
      console.log(obj.uname)	// pink老师
      console.log(obj['uname'])	// pink老师
      
  • 2️⃣
    • 语法:对象名.属性名 = 新值
    • 代码展示:
      obj.gender = '女'
      console.log(obj.gender)	// 女
      
  • 3️⃣
    • 语法:对象名.新属性名 = 新值
      obj.address = '武汉黑马'
      console.log(obj)	// {uname: 'pink老师', age: 18, gender: '女', address: '武汉黑马'}
      console.log(obj.address)	// 武汉黑马
      
  • 4️⃣删(了解)
    • 语法:delete 对象名.属性名
      delete obj.address
      console.log(obj)	// {uname: 'pink老师', age: 18, gender: '女'}
      

10.2.3 对象的方法

  • 方法 = 方法名 + 函数,它们之间用 : 分隔
  • 多个属性 之间 使用英文 , 分隔
  • 方法是依附在对象中的函数(外面函数对象内方法
  • 方法名可以使用 “”‘’ ,一般情况下省略,除非遇到特殊符号如 空格、中划线 等
  • 声明对象,并添加了若干方法后,可以使用,调用 对象 中的 (方法)函数,我们称之为方法调用
    • 语法:对象名.方法名()
    • 千万别忘了给方法名后面加 小括号
  • 代码展示:
    let obj = {
      uname: '刘德华',
      // 方法
      song: function () {
        console.log('冰雨')
      },
      getSum: function (x, y ) {
        x = x || 0
        y = y || 0
        console.log(x + y)
      }
    }
    
    // 方法调用 对象名.方法名()
    obj.song()				// 冰雨
    obj.getSum(2, 5)	// 7
    

10.3 ❗ 遍历对象

  • 1️⃣ for in 语法
    • 遍历的是 对象的属性 / 数组的索引 / 伪数组的索引 / 字符串的索引
      • 得到的索引都是字符串型
    for (let k in obj) {
      console.log(obj[k])
    }
    
    • 结论: k 是获得 对象属性名对象名[k] 是获得 对象属性值
  • 2️⃣ 判断一个成员在不在对象里面
    • 语法:
      属性/方法 in 对象名
      
    • 返回值: 布尔值 (true / false)
    • 代码展示:
      let obj = {
        uname: 'jack',
        age: 18,
        gender: '男',
        score: 100
      };
      console.log('name' in obj);	// true
      
  • 代码展示:
    //声明一个 obj 对象
    let obj = {
      uname: 'pink老师',
      age: 18,
      gender: '男'
    }
    
    // 用 fou in 循环遍历对象
    for (let k in obj) {		
      // k 可以是任何变量,选择 k/key 是因为许多程序员都在使用
      
      // console.log(k)      
      // k 是字符串型的,带有引号
      // k => 'uname' 'age' 'gender'
      // obj 对象里面没有 'uname'、 'age'、 'gender' 的属性名   ------    有引号
      // obj 对象里面的属性名是 uname、 age、 gender            ------    没有引号
      // 查询对象里面的属性有两种方法:1)对象名.属性名
      // 													2)对象名['属性名']
      // 原因:obj[k] === obj['uname'] === obj.uname
      //      obj[k] === obj['age'] === obj.age
      //	   obj[k] === obj['gender'] === obj.gender
      // 所以,利用for in循环遍历对象采用第二种查询方法
      // 结论:k 是获得对象的属性名 , 对象名[k] 是获得 属性值
      
      console.log(obj[k])	// 'pink老师'(string)  18(number)  '男'(string)
    }
    
  • 渲染学生信息
    • 代码展示:
      <!DOCTYPE html>
      <html lang="en">
      
      <head>
          <meta charset="UTF-8">
          <meta name="viewport" content="width=device-width, initial-scale=1.0">
          <title>Document</title>
          <style>
          table {
              width: 600px;
              text-align: center;
          }
      
          table,
          th,
          td {
              border: 1px solid #ccc;
              border-collapse: collapse;
          }
      
          caption {
              font-size: 18px;
              margin-bottom: 10px;
              font-weight: 700;
          }
      
          tr {
              height: 40px;
              cursor: pointer;
          }
      
          table tr:nth-child(1) {
              background-color: #ddd;
          }
      
          table tr:not(:first-child):hover {
              background-color: #eee;
          }
          </style>
      </head>
      
      <body>
          <h2>学生信息</h2>
          <p>将数据渲染到页面中...</p>
      
          <table>
              <caption>学生列表</caption>
              <tr>
                  <th>序号</th>
                  <th>姓名</th>
                  <th>年龄</th>
                  <th>性别</th>
                  <th>家乡</th>
              </tr>
              <script>
                  // 1.数据准备
                  let students = [
                      { name: '小明', age: 18, gender: '男', hometown: '河北省' },
                      { name: '小红', age: 19, gender: '女', hometown: '河南省' },
                      { name: '小刚', age: 17, gender: '男', hometown: '山西省' },
                      { name: '小丽', age: 18, gender: '女', hometown: '山东省' }
                  ]
      
                  // 2.开始渲染页面
                  for (let i = 0; i < students.length; i++) {
                      document.write(`
                      <tr>
                          <td>${i + 1}</td>
                          <td>${students[i].name}</td>
                          <td>${students[i].age}</td>
                          <td>${students[i].gender}</td>
                          <td>${students[i].hometown}</td>
                          </tr>
                      `)
                  }
              </script>
          </table>
      
      </body>
      
      </html>
      

10.4 内置对象

10.4.1 Math对象包含的方法

  • 1️⃣Math.random():生成0-1之间的随机小数(🔺包含0不包括1
    • 如何生成0-10的随机小数?
      • let num = Math.floor(Math.random() * (10 + 1))
        
    • 如何生成5-10的随机数?
      • let num = Math.floor((Math.random() * (5 + 1)) + 5
        
    • 如何生成N~M的随机数?
      • let num = Math.floor(Math.random() * (M - N + 1)) + N
        function getRandom (N, M) {
          // return Math.floor(Math.random() * (M - N + 1)) + N;
          return parseInt(Math.random() * (M - N + 1)) + N;
        }
        
    • 数组随机数:
      Math.floor(Math.random() * arr.length)
      
  • 2️⃣Math.ceil(数据):向上取整
    • 代码展示:
      console.log(Math.ceil(1.1))	// 2
      console.log(Math.ceil(1.01))	// 2
      
  • 3️⃣Math.floor(数据):向下取整
    • 代码展示:
      console.log(Math.floor(1.9))	// 1
      console.log(Math.floor(1.99))	// 1
      
  • 4️⃣Math.max(数据):找最大数
    • 代码展示:
      console.log(Math.max(0.1, 1, 65, 23, 88))  // 88
      
  • 5️⃣Math.min(数据):找最小数
    • 代码展示:
      console.log(Math.min(99, 65, 3, 0.1, -99))	// -99
      
  • 6️⃣pow:幂运算(了解)
  • 7️⃣Math.abs(数据):绝对值
    • 代码展示:
      console.log(Math.abs(-100))	// 100
      
  • 8️⃣Math.round(数据):四舍五入(取整数)
    • 代码展示:
      console.log(Math.round(2.45))	// 2
      console.log(Math.round(2.5))	// 3
      console.log(Math.round(-20.5))	// -20
      console.log(Math.round(-20.51))	// -21
      

贰、❗❗ Web APIS

  • Web API:是一套操作网页内容(DOM)与浏览器窗口(BOM)的对象
    • API:就是一些预定义好的方法,这些方法可以实现特定的功能,开发人员可以直接使用
    • Web API:浏览器提供了一套操作网页和浏览器的方法,通过这些方法可以轻松的操作元素和浏览器
  • 复杂数据类型const 声明:复杂数据类型 放在 里面,栈里面存放的地址指向堆里面存放的数据,变的只是堆里面存放的数据,存放数据的地址没有发生变化
  • 变量名 -> 栈地址-> 堆数据
  • const实际上指的并不是变量的值不得改动,
    其实说的是变量指向的那个内存空间中保存的数据不得改变
    简单数据类型是将值保存在栈中,所以用const声明简单数据类型时,值不得改变,相当于常量
    而复杂数据类型是将引用地址保存在栈中,具体的值保存在堆中
    那么用const声明复杂数据类型时,比如对象,数组时,只能保证的是这个地址是固定不变的
    堆中保存的数据是不是可变的,就无法保证了
    

一、❗❗ DOM(文档对象模型)

  • Document Object Model — 文档对象模型
  • 定义:是HTML文档的编程接口。它提供了对文档的结构化的表述,并定义了一种方式可以在从程序中对该结构进行访问,从而改变文档的结构,样式和内容。DOM 将文档解析为一个由节点和对象(包含属性和方法的对象)组成的结构集合。简言之,它会将 web 页面和程序语言连接起来。进而操作网页的内容,实现各种功能和部分特效。

1.1 DOM树 和 DOM对象

1.1.1 DOM树

  • DOM树:一种树状结构,把页面标签按照树状结构排列好,结构更加清晰
    • 每个DOM对象中都有表示层级关系的属性,利用这些属性把所有的DOM对象联系在一起,就形成一个树状结构,称为DOM树
  • 作用:文档树直观的 体现了 标签与标签 之间 的 关系image-20220725201648559

1.1.2 DOM对象

  • **DOM对象:**浏览器根据htm标签自动生成的JS对象
    • 浏览器把网页内容翻译成一个个的对象,把 网页内容 的 特征 翻译成 对象 的属性
  • document对象:是DOM里提供的一个对象(DOM里面最大的对象
    • 它提供的属性和方法都是 用来访问操作 网页内容

1.2 获取DOM对象

  • 打印对象:打印元素的时候,以对象的形式展现
    console.dir(对象);
    

1.2.1 ❗❗ 根据CSS选择器来获取DOM元素

  • 1️⃣ 选择匹配的 第一个 元素
    • 语法
      document.querySelector('css选择器')
      
    • 代码展示:
      const li = document.querySelector('ul li')
      
    • 参数:小括号里面 包含 一个 或 多个 有效的css选择器 字符串(引号)
    • 返回值
      • css选择器 匹配的 第一个元素,一个 HTMLElement 对象
      • ⚠ 如果 没有匹配 到元素就是 null
      • ⚠ 注意:必须加引号
  • 2️⃣ 选择匹配的 多个 元素
    • 语法
      document.querySelectorAll('css选择器')
      
    • 代码展示:
      const lis = document.querySelectorAll('li') //NodeList[li, li, li]
      
    • 参数:小括号里面 包含 一个 或 多个 有效的CSS选择器 字符串
    • 返回值
      • CSS选择器匹配的 NodeList 对象集合
      • 如果页面 不存在 这个 元素,得到的就是一个 空的伪数组
      • 所有 匹配的 元素 放到 NodeList🟨伪数组🟨 里面 返回
      • 有长度,有索引
      • 没有push(),pop()等数组方法
      • 想要得到里面的每一个对象,则需要遍历获得

1.2.2 获取HTML、body、head、title

document.documentElement	--- 	html
document.body			--- 	body
document.head			--- 	head			
document.title			--- 	title

1.2.3 ❌其他获取元素的方式

  • 1️⃣根据 id 获取元素
    • document.getElementById('id名称')
      
    • 注意:
      • id名称不加 #
  • 2️⃣根据 标签 获取 一类 元素
    • document.getElementsByTagName('标签名称')
      
    • 注意:
      • getElementsByTagName
      • 返回值:伪数组
  • 3️⃣根据 类名 获取元素
    • document.getElementsByClassName('类名')
      
    • 注意:
      • 类名不加 .
      • getElementsByClassName
      • 返回值:伪数组

1.3 操作元素内容

1.3.1 对象.innerText 属性

  • 元素 文本内容 添加/更新 到 任意标签 位置
  • 显示 纯文本不解析标签
  • 见代码展示

1.3.2 对象.innerHTML 属性

  • 元素内容 添加/更新 到任意标签位置
    • 包括标签、文本、注释
  • 会解析标签,多标签建议使用模板字符串
  • ⚠ 既要保留原来内容又要添加新内容,采用 字符串拼接 的方式
    • innerHTML += '要添加的文本'
      
  • 见代码展示
    代码展示
<div class="box"> 天地不仁以万物为刍狗!!! </div>
<strong>
    const box = document.querySelector('.box') 
    // 对象.innerText 属性
    box.innerText = '扶我起来,我还能干!!!'
    box.innerText = '<strong>扶我起来,我还能干!!!</strong>'
  
    // 对象.innerHTML 属性
    box.innerHTML = '扶我起来,我还能干!!!'
    box.innerHTML = '<strong>扶我起来,我还能干!!!</strong>'
</strong>
image-20220725223214605
  • innerText 和 innerHTML 的区别
    • innerText
      • 只能 获取 元素文本,无法 获取 标签
      • ⚠ 在获取文本的时候,包含 子元素 的 文本
    • innerHTML
      • 可以 获取对象里面的所有 文本+标签
    • 代码展示:
      <body>
          <div>
              123
              <p>456
              <span>789</span>
              </p>
          </div>
      
          <script>
              console.log(document.querySelector('div').innerText);
              console.log(document.querySelector('div').innerHTML);
          </script>
      </body>
      
image-20220816081122736

1.3.3 获取表单元素文本

  • 语法: 元素.value
  • 获取 输入的字符长度元素.value.length
  • ⚠ 获取 button 的文本依然使用 innerHTML(button双标签)
  • 拓展:
    • 元素.value.trim() - 去除字符串 左右两侧 的空格

1.4 操作元素属性

1.4.1 操作 元素 属性

  • 语法元素.属性 = ‘值’
    • 代码展示:
      <img src="./images/1.webp" alt="">
      //随机数函数
      function getRandom(N, M) {
        return Math.floor(Math.random() * (M- N + 1)) + N
      }
      //获取图片对象
      //img在html中是标签,在js中是对象
      const pic = document.querySelector('img')
      // 修改对象的属性值
      pic.src = `./images/${getRandom(1, 6) }.webp`
      

1.4.2 控制 样式 属性

  • 1️⃣ 通过 style属性 操作css
    • 语法元素.style.样式属性 = ‘值’
      • 对于复杂的样式属性建议使用 小驼峰 命名法
      • 生成的是 行内样式表,权重很高,只有 !important 能做掉它
      • ⚠🔺 只写 属性
    • 代码展示:
      // 获取对象(元素)
      const box = document.querySelector('div')
      // 修改样式属性 对象.style.样式属性 = '值'
      box.style.width = '400px'
      box.style.height = '100px'
      box.style.backgroundColor = 'red'
      box.style['background-color'] = 'green'
      
  • 2️⃣ 通过 类名(className) 操作css
    • 语法:元素.className = ‘类名’
      • 注意:会覆盖前面的类名 新值换旧值
      • 想要原来的类名 -> 元素.className = ‘旧类名 新类名’
    • 代码展示:
      <style>
        div {
          width: 200px;
          height: 200px;
          background-color: pink;
        }
        .active {
          width: 300px;
          height: 300px;
          background-color: hotpink;
          margin-left: 100px;
        }
      </style>
      
      <body>
        <div class="one"></div>
        <script>
          // 1.获取元素
          // let box = document.querySelector('css选择器')
          let box = document.querySelector('div')
          // 2 给div添加类名 class 是个关键字,选用className替代它
          // 新值换旧值,会覆盖原来的类名
          box.className = 'active'
          // 用旧类名+新类名的形式覆盖原来的类名
          box.className = 'one active'
        </script>
      </body>
      
  • ❗3️⃣ 通过 classList 操作类 控制css
    • 语法
      • 追加 类:元素.classList.add(‘类名’)
      • 删除 类:元素.classList.remove(‘类名’)
      • 切换 类:元素.classList.toggle(‘类名’)
        • 如果有这个类名就是删掉,没有就追加
      • 替换 类:元素.classList.replace(‘旧类名’, ‘新类名’)
        • 两个参数,第一个是原来的类名,第二个参数是替换的类名
      • 是否包含指定的 类:元素.classList.contains(‘类名’)
        • 判断是否包含指定的类名,返回值是布尔值 true / false
    • ⚠ 注意:
      • 类名 不加 点,并且 是 字符串
      • 方法,注意加小括号
    • 代码展示:
      // 获取对象
      const box = document.querySelector('.one')
      
      // 追加类名
      box.classList.add('two')
      box.classList.add('three')
      
      // 删除类名
      box.classList.remove('three')
      
      // 切换类名
      // 如果有这个类名就是删除,没有就是追加
      box.classList.toggle('ab')
      box.classList.toggle('one')
      
      // 替换类名
      // 将 旧类名box 替换成 新类名box1
      box.classList.replace('box', 'box1')
      
      // 判断是否包含指定的类名
      console.log(box.classList.contains('box'))		// true
      
image-20220726101208459
  • classList 和 className区别
    • classList追加类名,将新类名追加到旧类名后面,不影响以前的类名
    • className覆盖类名,新类名 覆盖 旧类名,影响以前的类名

1.4.3❗❗ 操作 表单元素 属性

  • 语法
    • 获取元素.属性名
    • 设置元素.属性名 = 新值
  • 代码展示:获取表单里面的值
    const input = document.querySelector('.computer')
    console.log(input.value)
    input.value = '扶我起来,我还能干!!!'
    
  • ⚠ 注意:对象.innerHTML 只能获取 普通元素文本,获取 表单元素文本 需要使用 对象.value
    • 注意: 对象.value 获得的文本是 包含 首尾空白符
      • 想要获得 有效的文本 需要使用 trim() 方法[对象.value.trim()],删除首尾的空白符
    • ⚠注意:获取 button 的文本还是用 innerHTML
  • 表单属性中添加就有效果,移除就没有效果,一律使用 布尔值 表示,如果为 true 代表 添加 了该 属性 ,如果是 false 代表 移除属性
    • disabled(禁用)、checked(选中)
    • 除了 ’ 'false0nullundefinedNaN 其余的都是true,但是不建议写,建议写布尔值
    • 代码展示:
      <input type="checkbox" value="" name="">
      const input = document.querySelector('.computer')
      input.checked = true	// 让复选框选中
      input.checked = false	// 让复选框不选中
      input.disable = true	// 禁用吗? - 禁用(true)
      input.disable = false // 禁用吗? - 不禁用(false默认值)
      

1.4.4 ❗❗ 自定义属性

  • 属性
    • 标准属性:标签天生自带的属性,可以直接使用 点语法 操作
    • 自定义属性:
      • 在h5中推出了专门的 data- 自定义属性
      • 在标签上一律以 data- 开头(必须以 data- 开头)
      • 在DOM对象上一律以 dataset 对象方式获取
      • dataset 是一个 自定义属性集合包含 该标签内所有 自定义属性
      • 代码展示:
        <div data-id="1" data-spm="不知道">1</div>
        <div data-id="2">2</div>
        <div data-id="3">3</div>
        <div data-id="4">4</div>
        <div data-id="5">5</div>
        <script>
          // 获取元素
          const one = document.querySelector('div')
        	// one是一个HtmlElement对象
        	console.log(one)
        	// dataset是一个对象集合
        	console.log(one.dataset)
        	// 获取dataset对象里面的id属性
        	console.log(one.dataset.id)
        	// 获取dataset对象里面的spm属性
        	console.log(one.dataset.spm)
        </script>
        
      image-20220726160921554
  • ❌⛔ 拓展:
    • 获取自己 瞎定义的属性
    • 浏览器不会识别 瞎定义属性,并且它不会体现在DOM对象上
    • 语法:
      DOM对象.getAttribute(瞎定义属性名)
      

1.5 ❗❗ 定时器 - 间歇函数

  • 定时器 = setInterval() + setTimeout()
  • setInterval(函数, 间隔时间)(间歇函数):按照指定的周期(以毫秒计)来调用函数或计算表达式。方法会不停地调用函数,直到clearInterval()被调用或窗口关闭
    • 间歇函数可以根据时间自动重复执行某些代码
  • setTimeout(函数, 延迟时间)(延时函数):在指定的毫秒数后调用函数或计算表达式 (Timeout - 超出)
  • 定时器 里面的 第一个参数 是 回调函数
    • 将一个函数作为参数传递给另外一个函数,这个函数就是回调函数

1.5.1 开启定时器

  • 语法
    匿名函数:setInterval(函数, 间隔时间)		// Interval - 间隔,间隙
    具名函数:setInterval(函数名, 间隔时间)
    
  • 作用:每隔一段时间 回头调用函数(先隔段时间 ,再调用函数)
    • 间隔时间 单位 是 毫秒(ms),不用写
    • 不是立即调用函数,时间间隔 过后再去 调用函数
  • 间歇函数返回值
    • 表示 当前定时器 是 页面中 的 第几个 定时器,是一个 id数字数字型)(唯一的)
    • 一个 间歇函数 只有 一个 返回值,并且是唯一
  • 代码展示:
    // 匿名函数
    setInterval(() => {
      console.log('扶我起来,我还能干!!!')
    }, 1000)
    
    // 具名函数
    function fn() {
      console.log('扶我起来,我还能干!!!')
    }
    setInterval(fn, 1000)
    // fn() --- 执行这个函数,只执行一次 (fn()调用这个函数)
    // fn --- 每隔一段时间,回头去找fn这个函数(自动调用),再执行(fn是一个变量,代表这个函数)
    
    // 定时器的返回值,是数字型,是id
    // 声明一个变量,接收定时器的返回值
    let n = setInterval(() => {
      console.log(1)
    }, 1000)
    console.log(n)			// 1
    
    function fn() {
      console.log('扶我起来,我还能干!!!')
    }
    let m = setInterval(fn, 1000)
    console.log(m)			// 2
    

1.5.2 关闭定时器

  • 语法
    // 匿名函数
    let 变量名 = setInterval(函数, 时间间隔)
    // 具名函数
    let 变量名 = setInterval(函数名, 时间间隔)
    clearInterval(变量)
    
  • 代码展示:
    // 匿名函数
    let n = setInterval(() => {
      console.log(11)
    }, 1000)
    
    // 具名函数
    function fn() {
      console.log('扶我起来,我还能干!!!')
    }
    let m = setInterval(fn, 1000)
    
    // 关闭定时器
    clearInterval(n)
    clearInterval(m)
    

二、❗❗ DOM事件基础

2.1 事件监听(绑定)

  • 让程序检测是否有事件产生,一旦事件触发,就立即调用一个函数做出响应,也称为 绑定事件 / 注册事件
  • 事件监听三要素:
    • 事件源
    • 事件类型
    • 事件调用的函数(事件处理函数)
  • 语法
    元素对象.addEventListener('事件类型', 要执行的函数)
    
  • ⚠ 注意:事件类型 要加 引号
    • L2 注册的 事件 不会 出现 覆盖
    • L0 注册的事件会发生覆盖(后面的覆盖前面的)(同对象、同事件类型)
  • 代码展示:
    // 获取元素
    const btn = document.querySelector('button')
    // 事件监听-点击事件
    btn.addEventListener('click', () => {
      alert('扶我起来,我还能干!!!')
    })
    

2.2 事件类型

2.2.1 鼠标事件

  • 1️⃣ click - 鼠标点击
  • 2️⃣ mouseenter - 鼠标经过
  • 3️⃣ mouseleave - 鼠标离开
  • 4️⃣ mousemove - 鼠标移动
  • 5️⃣ dblclick - 鼠标左键双击

2.2.2 焦点事件

  • 1️⃣ focus - 获得焦点
  • 2️⃣ blur - 失去焦点

2.2.3 键盘事件

  • 1️⃣ keydown - 键盘按下触发
  • 2️⃣ keyup - 键盘抬起触发
  • 注意: 用鼠标粘贴内容不会触发

2.2.4 文本事件

  • 1️⃣ input - 用户输入事件
    • 获取用户 输入文本对象.value
    • 获取用户 输入文本长度对象.value.length
      • 注意:
        • 得到的 是 数字型
        • 包括 左右两侧 的 空格
    • 想要获得 有效文本和长度 (不包括首尾的空白符)
      • 有效文本: 对象.value.trim()
      • 有效长度: 对象.value.trim().length
      • trim() 方法:删除 字符串 首尾 空白符(空格、制表符、换行符等其他空白符)
      • 不会 改变 原始字符串
      • 不适用于null,undefined,Number类型

2.2.5 表单事件

  • 1️⃣ submit - 提交事件
  • 2️⃣ change - 失去焦点并且表单内容发生改变触发事件
  • 3️⃣ 重置表单: form.reset()

2.2.6 光标的坐标

  • 1️⃣ clientX 和 clientY
    • 光标距相对于 浏览器 可视化窗口 左上角 的位置
    • 鼠标在窗口中的位置
  • 2️⃣ pageX 和 pageY
    • 光标距离 文档流 左上角 的位置
    • 鼠标在页面中的坐标
    • 计算鼠标在某个盒子中的坐标:
      • 鼠标到盒子顶部的距离 = 鼠标到页面顶部的距离 - 盒子顶部到页面顶部的距离
      • 鼠标到盒子左侧的距离 = 鼠标到页面左侧的距离 - 盒子左侧到页面左侧的距离
    • image-20220814150651433
  • 3️⃣ offsetX 和 offsetY
    • 光标距离 DOM元素 左上角 的位置
    • 鼠标在标签中的位置
  • ⚠🔺 拓展:利用 js 调用 事件
    • 语法:元素.事件类型()

2.3 事件对象 - event

  • 也是个对象,里面有事件触发时相关的信息

2.3.1 获取事件对象

  • ⚠ 使用场景:
    • 可以判断用户按下哪个键
    • 可以判断鼠标点击了哪个元素,从而做相应的操作
  • 语法:
    • 事件绑定回调函数第一个参数 就是 事件对象
    • 一般命名为 event、ev、e
    • element.addEventListener('事件类型', function (e) {})
      
  • 在触发 DOM 上的某个事件时,会产生一个事件对象
  • event对象 包含与创建它的特定相关的和方法

2.3.2 事件对象常用属性

  • type获取 当前的 事件类型
  • clientX / clientY:获取 光标 相对于 浏览器可视化窗口 左上角 的位置
  • offsetX / offsetY:获取 光标 相对于 当前DOM元素 左上角 的位置
  • pageX / pageY : 光标距离 文档流 左上角 的位置
  • key
    • 用户 按下 键盘键的值
    • 现在不提倡使用keyCode
  • 代码展示:
    元素.addEventListener('click', function (e) {
      console.log(e.key)
      console.log(e.type)
    })
    

2.4 环境对象

  • 函数内部特殊的变量 this,代表当前函数运行时所处的环境
  • 每个函0数 里面 都有 this
  • 非严格模式
    • this指向函数的调用者(普通函数里面 this -> window)
    • 事件侦听里面,指向事件源
    • 箭头函数没有this(箭头函数不会自己创建this,它只会沿用自己所在这条作用域链的上层作用域的this)
    • 定时器里面this指向window

2.5 回调函数

  • 官方:如果将函数A作为参数传递给函数B时,我们称函数A为 回调函数
  • 把一个 函数 当作 参数 来 传递给 另外一个函数 的时候,这个函数就是 回调函数

三、❗❗ DOM事件进阶

3.1 事件流

3.1.1 事件流与两个阶段说明

  • 事件流 = 事件捕获 + 事件目标 + 事件冒泡
    • 事件流指的是:事件 完整执行过程 中的 流动路径
    • 过程:事件捕获 => 事件目标阶段 => 事件冒泡 整个完整的过程就是事件流
  • 两个阶段:
    • 捕获阶段:从父到子(从大到小)
    • 冒泡阶段:从子到父(从小到大)
    • 实际工作中都是使用 事件冒泡 为主
  • image-20220731230107629

3.1.2 ❌ 事件捕获(了解)

  • 概念:从DOM的 根元素 开始去执行对应的事件(从外到里)
  • 事件捕获需要写对应代码才能看见效果
    • 代码:
      DOM.addEventListener(事件类型, 事件处理函数[, 是否使用捕获机制 = false])
      
      • addEventListener第三个参数传入 true 代表是捕获阶段触发(很少使用)
      • 若传入false代表冒泡阶段触发,默认就是false
      • 若是用 L0(on事件类型) 事件监听,则只有冒泡阶段,没有捕获

3.1.3 事件冒泡

  • 从子到父(从小到大)
  • 概念:当一个元素触发事件后,会 依次 向上 调用 所有父级元素同名事件(同种事件类型)
  • 事件冒泡是默认存在的
  • 事件冒泡的必要性
    • 如果没有冒泡,给大盒子注册点击事件,点击的是里面的小盒子,会导致大盒子的点击无法执行
    • 事件委托(委托给祖先元素)
  • L2事件监听第三个参数是false,或者默认都是冒泡
  • 代码展示:
    const fa = document.querySelector('.father')
    const son = document.querySelector('.son')
    document.addEventListener('click', function () {
      alert('我是爷爷')
    })
    fa.addEventListener('click', function () {
      alert('我是爸爸')
    })
    son.addEventListener('click', function () {
      alert('我是儿子')
    })
    // 事件冒泡:从子到父
    // 弹出框的顺序依次是:儿子 -> 我是爸爸 -> 我是爷爷
    

3.1.4 阻止冒泡

  • 语法:
    事件对象.stopPropagation()		// 方法		停止传播		sp(快捷)
    e.stopPropagation()
    // 事件对象 - 回调函数的第一个参数
    
    • 此方法可以阻断事件流动传播 ,不光在冒泡阶段有效,捕获阶段也有效
  • 代码展示:
    const fa = document.querySelector('.father')
    const son = document.querySelector('.son')
    document.addEventListener('click', function () {
      alert('我是爷爷')
    })
    fa.addEventListener('click', function () {
      alert('我是爸爸')
    })
    son.addEventListener('click', function (e) {
      alert('我是儿子')
      // 阻止流动传播(阻止事件冒泡)
      // 在这一块卡住,不允许向上传播
      e.stopPropagation()
    })
    // 弹出框:我是儿子
    
  • 阻止元素默认行为:
    • 语法:
      e.preventDefault()		// 方法 阻止默认	pd(快捷)
      // 阻止 链接跳转
      // 阻止 表单提交(缺点:提交数据页面h)
      
    • 代码展示:
      <body>
        <form action="http://www.itcast.cn">
          <input type="submit" value="免费注册">
        </form>
        <a href="http://www.baidu.com">百度一下</a>
        <script>
          // 获取元素
          const a = document.querySelector('a')
          const form = document.querySelector('form')
          // 事件侦听-a-点击事件
          a.addEventListener('click', function (e) {
            // 阻止a的默认行为-页面跳转
            e.preventDefault()
          })
          // 事件侦听-form-提交事件
          form.addEventListener('submit', function (e) {
            // 阻止form的默认行为-表单的提交
            e.preventDefault()
          })
        </script>
      </body>
      

3.1.5 两种鼠标事件的区别

  • 注意:
    • mouseover 和 mouseout 会 有 冒泡效果
    • mouseenter 和 mouseleave 没有 冒泡效果(推荐)

3.1.6 解绑事件

  • 1️⃣ L0事件解绑(on方式)
    • 直接使用 null 覆盖就可以实现事件的解绑
    • 代码展示:
      btn.onclick = function () {
        alert('点击了')
      }
      // L0事件移除解绑
      btn.onclick = null
      
  • 2️⃣ L2 事件解绑
    • 语法:

      removeEventListener(事件类型, 函数名[, 获取捕获或冒泡阶段])
      
      • ⚠ 中括号包裹的参数可以省略
      • ⚠🔺 匿名函数 无法进行 事件解绑 操作
      • ⚠ 解绑的时候必须是 同一个函数(两个函数体一样 的 匿名函数 不是 同一个函数)
    • 代码展示:

      <script>
        // 获取元素
        const btn = document.querySelector('button')
      	// 声明函数
      	let fn = function (e) {
                  alert(`事件解绑语法:
                  元素.removeEventListener(事件类型, 函数名)
                  匿名函数 无法进行 事件解绑 操作
                  ${e.target.tagName}
                `)
              }
      	// 事件侦听-点击事件
      	btn.addEventListener('click', fn)
      	// 事件解绑
      	btn.removeEventListener('click', fn)
      </script>
      

3.1.7 两种注册事件的区别

  • 1️⃣ 传统on 注册(L0)
    • 同一个对象,后面注册的事件会 覆盖 前面注册的事件(同一个事件
    • 直接使用 null 覆盖就可以实现事件的解绑
    • 都是 冒泡阶段 执行的(只有冒泡没有捕获)
  • 2️⃣ 事件监听 注册(L2)
    • 语法:addEventListener(事件类型, 事件处理函数[ , 是否使用捕获 = false])
      • 既能捕获也能冒泡
      • 捕获 将第三个参数 改成 true
      • 冒泡不用写,默认就是冒泡(false)
    • 后面注册的事件 不会覆盖 前面注册的事件(同一个事件
    • 可以通过 第三个参数 去确定是在 冒泡阶段 或者 捕获阶段 执行的
    • 必须使用 removeEventListener(事件类型, 事件处理函数[ , 获取捕获或者冒泡阶段])
    • ⚠🔺 匿名函数无法解绑

3.2 事件委托

  • 优点:
    • 减少注册次数
    • 提高程序性能
    • ⚠ 为未来元素预备事件(添加节点)
  • 原理: 事件委托其实是利用 事件冒泡 的特点
    • 父元素 注册事件,当我们触发子元素的时候,会冒泡到父元素身上,从而触发父元素的事件
  • 注意: 事件触发元素嵌套关系很复杂就不可以使用事件委托
  • 实现:
    • 获得 真正 触发事件 的 元素(对象):事件对象.target
    • 获得 真正 触发事件元素 的 标签名称:事件对象.target.tagName
  • 代码展示:
    <body>
      <ul>
          <li>第1个孩子</li>
          <li>第2个孩子</li>
          <li>第3个孩子</li>
          <li>第4个孩子</li>
          <li>第5个孩子</li>
          <p>我不需要变色</p>
      </ul>
      <script>
          // 1.点击每个小li,当前li文字变色
          // 按照事件委托的方式,委托给父级,事件写到父级身上
          // 获取元素
          const ul = document.querySelector('ul')
          // 事件绑定
          ul.addEventListener('click', function (e) {
              // e:事件对象
              // 得到一个事件对象
              // console.log(e)
              // 得到被点击的元素
              // console.log(e.target)
              // 得到被点击元素的标签名称
              // 得到的标签名称是 大写的 字符串
              // console.log(e.target.tagName)	// 'LI'
              // 判断点击的是不是li,如果是li文字就变颜色
              if (e.target.tagName === 'LI') {
                  e.target.style.color = 'red'
              }
          })
      </script>
    </body>
    

3.3 其他事件

3.3.1 页面加载事件

  • ⚠ JavaScript 写在body上面,必须 使用 load事件 或者 DOMContentLoaded事件
  • 1️⃣ load 事件
    • 等待页面 所有外部资源(外联CSS、外联JavaScript,图片……) 加载完毕 时,就回去执行回调函数
    • 事件名: load(等待)
    • 监听 整个页面 所有外部资源 加载完毕
      • ⚠ 给 window 添加 load 事件
      • 语法:
        window.addEventListener('load', function () {
          //	执行操作
        })
        
      • 代码展示:script标签在body标签上方
        <script>
          // 给 window 添加 页面加载事件(load)
          window.addEventListener('load', function () {
          // 获取元素
          const btn = document.querySelector('button')
          // 事件侦听-点击事件
          btn.addEventListener('click', function () {
            alert(`
               页面加载事件
               给 window 添加 load 事件
               window.addEventListener('load', function() {})
              `)
          })
        })
        </script>
        <body>
          <button>点击</button>
        </body>
        
      • ⚠ 注意:不光可以监听整个页面资源加载完毕,也可以针对某个资源绑定 load事件
  • 2️⃣ DOMContentLoaded 事件
    • 初始的HTML文档(DOM节点) 被完全加载和解析完成之后,DOMContentLoaded事件被触发,而无需等待外部资源加载
    • 事件名: DOMContentLoaded
    • 监听页面 DOM节点 加载完毕
      • ⚠ 给 document 添加 DOMContentLoaded 事件
      • 语法:
        document.addEventListener('DOMContentLoaded', function () {
          // 执行的操作
        })
        
      • 代码展示:
        document.addEventListener('DOMContentLoaded', function () {
          // 获取元素
          const btn = document.querySelector('button')
          // 事件侦听-点击事件
          btn.addEventListener('click', function () {
            alert(`
                页面加载事件
                给 document 添加 DOMContentLoaded 事件
                document.addEventListener('DOMContentLoaded', function() {})
              `)
          })
        })
        

3.3.2 元素滚动事件 - scroll

  • 滚动条 滚动的时候 触发(⚠ 页面 必须有 滚动条 才能 触发
    • 让 页面 具有 滑动效果 (不是瞬间到指定位置,而是缓慢滑动到指定位置)
      • /* 页面滑动 */
        html {
          /* 让滚动条丝滑的滑动 */
          /* 滚动-行为:平滑 */
          scroll-behavior: smooth;
        }
        
  • 让 html标签(页面最大的标签) 滚动
    • document.documentElement.scrollTop // html被卷去的高度
      window.pageYoffset		// 页面滚出去的高度(页面在竖轴的偏移量)
      document.documentElement.scrollTop === window.pageYoffset
      
  • 应用场景:固定导航栏、返回顶部
  • 事件名: scroll
  • 监听 整个页面 滚动
    • 语法:
      window.addEventListener('scroll', function () {
        // 执行的操作
      })
      
    • ⚠ 注意:
      • 给 window(常用) 或 document 添加 scroll 事件
      • 监听 某个元素的内部 滚动 直接给 某个元素 加即可
    • 代码展示:
  • 获取位置
    • scrollTop(被卷去的头部) 和 scrollLeft(被卷去的左侧) (属性)
      • ⚠🔺 读写属性(可以 读取 亦可以 赋值)
      • ⚠ 获取到的是 数字,赋值的时候 不带单位
      • 检测页面滚动的头部距离
        • document.documentElement.scrollTop = 数字
          
        • window.pageYoffset - 只读属性
          
      • 获取 被卷去 的大小
      • 获取 元素内容 往左、往上滚出去 看不到距离
      • ⚠ 得到的是:数字型 不带单位
      • 尽量写在 scroll事件 里面
      • 代码展示:
      <style>
        * {
          margin: 0;
          padding: 0;
          box-sizing: border-box;
        }
      
        body {
          height: 3000px;
        }
      
        div {
          display: none;
          margin: 100px auto;
          width: 470px;
          height: 150px;
          border: 1px solid #000;
          text-align: center;
          font-size: 20px;
          font-family: '隶书';
        }
      
        .active {
          display: block;
          position: fixed;
          top: 0;
          left: 50%;
          transform: translateX(-50%);
          margin-top: 0;
        }
      </style>
      
      <body>
        <div>
          世间的悲喜皆不如我所愿,但苦于乐皆是恩赐!!!
          世间的悲喜皆不如我所愿,但苦于乐皆是恩赐!!!
          世间的悲喜皆不如我所愿,但苦于乐皆是恩赐!!!
          世间的悲喜皆不如我所愿,但苦于乐皆是恩赐!!!
          世间的悲喜皆不如我所愿,但苦于乐皆是恩赐!!!
          世间的悲喜皆不如我所愿,但苦于乐皆是恩赐!!!
        </div>
        <script>
          // 事件侦听-页面滚动事件-window
          window.addEventListener('scroll', function () {
            // 获取html元素
            const html = document.documentElement
            // 获取div元素
            const div = document.querySelector('div')
            // console.log(html.scrollTop);		// 得到的是数字型
            // scrollTop >= 300显示div并固定在可视区域顶部,小于300隐藏
            if (html.scrollTop >= 300) {
              div.classList.add('active')
            } else {
              div.classList.remove('active')
            }
          })
        </script>
      </body>
      
    • 让页面 滚动到指定位置
      • 1️⃣ 属性赋值
        document.documentElement.scrollTop = 指定位置距离顶部的距离
        
      • 2️⃣ 方法
        window.scrollTo(x, y)
        

3.3.3 ❌ 页面尺寸事件 - resize(了解)

  • 窗口尺寸改变 的时候 触发事件
    • 事件类型: resize
    • 语法:
      window.addEventListener('resize', function () {
        // 执行的代码
      })
      
  • 检测屏幕宽度
    • 语法:
      window.addEventListener('resize', function () {
        let w = document.documentElement.clientWidth
        console.log(w)
      })
      
  • 获取元素宽高 (属性)
    • 获取元素的 可见部分 宽高(不包含border、margin、滚动条)
    • clientWidthclientHeight
    • 得到的是 数字型
    • image-20220802140421274

3.4 ❗❗ 元素的尺寸和位置

  • 1️⃣ 获取 宽高:(属性)
    • 获取元素 自身的宽高
      • 内容 + padding + border
    • offsetWidthoffsetHeight
    • 获取到的是 数值
    • ⚠ 获取的是 可视宽高,如果盒子是隐藏的,获取的结果是0
  • 2️⃣ 🔻 获取 位置:
    • ① 获取元素 距离自己 最近一级 定位 祖先元素左、上 距离
      • 带有 定位属性 的 祖先元素
      • 如果都没有,就以文档左上角为准
    • offsetLeftoffsetTop
      • 相对于 页面 来说
      • 只读属性
    • 获取的是可视宽高,若盒子隐藏,则获得的是0
    • ② ❌ 元素.getBoundingClientRect() (了解)
      • 返回元素的 大小 及其 相对于视口的位置
      • 相对于 视口
      • 代码展示:
        const div = document.querySelector('div')
        div.getBoundingClientRect()
        
    image-20220802172910019

总结

属性作用说明
scrollLeftscrollTop卷去头部左侧配合 页面滚动(scroll 事件) 来用,可读写
clientWidthclientHeight获得 元素宽度高度不包含border、margin、滚动条,用于js 获取元素大小 只读属性
offsetWidthoffsetHeight获得 元素宽度高度包含border、padding、滚动条等,只读属性
offsetLeftoffsetTop获取元素距离 自己定位父元素 的左、上距离获取 元素位置 的时候使用,只读属性
  • scroll系列 、 client系列 、 offset系列
    • scroll系列: 标签内部 内容 的大小,位置
      • scrollTop / scrollLeft:表示标签真实内容相对于标签的位置
      • ❌scrollWidth / scrollHeight:表示标签真实内容的大小(和标签本身的大小无关,是内容的宽高)
    • client系列: 标签 容纳范围(border里面) 的大小、位置
      • clientWidth / clientHeight:表示标签内容区域的大小
      • ❌clientTop / clientLeft:表示标签内容区域的位置(几乎不用,仅仅表示上边框的高度,左边框的宽度)
    • ✔🔻 offset系列: 标签本身 的大小、位置
      • offsetWidth / offsetHeight:包含content + padding + border
      • offsetTop / offsetLeft:最近一级带有定位属性祖先元素 的 相对位置(如果没有定位,那么就是相对于body)
  • 拓展:
    • 添加css让页面滚动平滑
      • html {
          scroll-behavior: smooth;
        }
        
    • if单分支语句拓展:
      • if (old) old.classList.remove('active')
        
      • old && old.classList.remove('active') - 逻辑与
        
      • old?.classList.remove('active') - 可选链
        
    • 属性选择器
      • document.querySelector('[data-name=new]')
        自定义属性 的 属性值 可以 省略 双引号(不推荐)
        

四、❗❗ 日期对象

  • 用来 表示时间 的 对象
  • 作用: 得到 当前系统时间
  • 日期对象:Date构造函数的实例,记录了一个时间信息

4.1 实例化

  • 实例化:有 new 关键字的都是实例化(见 JS 高级)

4.1.1 得到当前时间

  • 创建一个 时间对象 并 获取时间
    • 语法:
      const 常量名 = new Date()
      
    • 代码展示:
      const date = new Date()
      console.log(date)
      // Wed Aug 03 2022 20:37:52 GMT+0800 (中国标准时间)
      // 周三 八月 3号 年份 时间 
      

4.1.2 指定时间

  • 倒计时 的时候 使用
  • 语法:
    const 常量名 = new Date('指定的时间')
    
  • 参数:
    • 数字 : 月份是从 0 开始的
    • 字符串 : 月份是正常的
  • 代码展示:
    const date = new Date('2022-8-3 20:50:00')
    let h = date.getHours()
    console.log(h)	// number
    console.log(date)
    console.log(typeof date)	// object
    // Wed Aug 03 2022 20:50:00 GMT+0800 (中国标准时间)
    

4.2 日期对象方法

  • 语法作用说明
    对象.getFullYear()获得 年份获取 四位 年份
    对象.getMonth()获得 月份取值为 0 ~ 11
    对象.getDate()获取 月份中的 某一天不同月份取值不同
    对象.getDay()获取 星期取值为 0 ~ 6
    对象.getHours()获取 小时取值为 0 ~ 23
    对象.getMinutes()获取 分钟取值为 0 ~ 56
    对象.getSeconds()获取 取值为 0 ~ 59
    对象.getMilliseconds()获取 毫秒取值为 0~1000
  • 注意:
    • 周日是一周的开始 -> 周日 = 0
    • 当前月份 = 获取的月份 + 1
    • ⚠ 得到的都是 数字型

4.3 时间的另一种写法

  • 时间对象.toLocaleString() :年月日时分秒
  • 时间对象.toLocaleDateString() :年月日
  • 时间对象.toLocaleTimeString() :时分秒
  • 代码展示:
    // 获得当前系统时间
    const systemTime = new Date()
    // 从 获取的当前系统时间(systemTime)里找
    // 获取年份
    const year = systemTime.getFullYear()
    // 获得月份
    const month = systemTime.getMonth() + 1
    // 获取月份中的某一天
    const date = systemTime.getDate()
    // 获取星期
    const day = systemTime.getDay()
    // 获取小时
    const hours = systemTime.getHours()
    // 获取分钟
    const minutes = systemTime.getMinutes()
    // 获取秒
    const seconds = systemTime.getSeconds()
    console.log(systemTime);
    console.log(`${year}${month}${date} 日 周${day}  ${hours}${minutes}${seconds}`)
    // Wed Aug 03 2022 21:14:56 GMT+0800 (中国标准时间)
    // 2022 年 8 月 3 日 周3  21 时 14 分 56 秒
    
  • 格式化时间:
    <!DOCTYPE html>
      <html lang="en">
    
       <head>
       <meta charset="UTF-8">
       <meta http-equiv="X-UA-Compatible" content="IE=edge">
       <meta name="viewport" content="width=device-width, initial-scale=1.0">
       <title>Document</title>
    <style>
     * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
    	}
    
    	div {
      	margin: 100px auto;
      	width: 600px;
      	height: 100px;
      	border: 5px solid #969696;
      	background-color: #d7d7d7;
      	color: hsl(338, 100%, 50%);
      	font-size: 44px;
      	font-weight: 700;
      	font-family: '华文隶书';
      	text-align: center;
      	line-height: 100px;
    	}
    </style>
    </head>
    
    <body>
      <div></div>
      <script>
          // 写法一:  
      	const div = document.querySelector('div')
              function getTime() {
                  const date = new Date()
                  let hours = date.getHours() < 10 ? '0' + date.getHours() : date.getHours()
                  let minutes = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes()
                  let seconds = date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds()
                  return `当前时间:${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()} 	${hours}:${minutes}:${seconds}`
              }
              
              div.innerHTML = getTime()
              setInterval(function () {
                   div.innerHTML = getTime()
              }, 1000)
              // 当前时间:2022-8-3 22:45:50
    
              // 写法二:自动补0
              /*
                  // 定时器外面再写一次的原因:定时器隔1s再去执行,用外面的填补页面空白
                  div.innerHTML = date.toLocaleString()
                  // div.innerHTML = date.toLocaleDateString()
                  // div.innerHTML = date.toLocaleTimeString()
                  setInterval(function () {
                      const date = new Date()
                      div.innerHTML = date.toLocaleString()	 // 2022/8/3 23:00:00
                      // div.innerHTML = date.toLocaleDateString()    // 2022/8/3
                      // div.innerHTML = date.toLocaleTimeString()    // 22:48:20
                  }, 1000)
              */
      </script>
    </body>
    </html>
    

4.3 时间戳

  • 使用场景:倒计时
  • 时间戳: 是指1970年01月01日00时00分00秒起 至现在毫秒数
  • 注意:
    • 时间戳唯一的
    • ⚠ 中国 在 东8区
      const date = +new Date('1970-01-01 00:00:00') / 1000 / 60 / 60
      console.log(date)	// -8
      
  • ⚠🔻 算法
    • 将来的时间戳 - 当前的时间戳 = 剩余时间毫秒数
    • 剩余时间毫秒数 转换为 剩余时间的 日时分秒 就是 倒计时
    • 展示:
      将来时间戳 2000ms - 现在时间戳 1000ms = 1000ms
      1000ms 转换时分秒就是 0小时0分1秒
      
  • 三种获取时间戳的方法:
    • 1️⃣ 使用 getTime() 方法
      • 语法:
        const date = new Date()
        console.log(date.getTime())	// 1659539589145 毫秒数
        // new Date().get.Time()
        拓展:
        时间对象.getTime() 和 时间对象.valueOf() 的到的结果一样
        console.log(date.getTime() === date.valueOf())	// true
        
      • 注意:
        • 必须 先 实例化
        • ⚠ 可以返回 指定时间的时间戳
    • 2️⃣ ✔简写 +new Date()
      • 语法:
        console.log(+new Date())  // 1659539732765 毫秒数
        
      • 注意:
        • + -> 正号 (隐式转换)
        • ⚠ 可以返回 指定时间的时间戳
          • 代码展示:
            conlose.log(+new Date('2022-10-1 07:30:00'))
            // 1664580600000 -- 指定时间的时间戳
            
    • 3️⃣ 使用 Date.now()
      • 语法:
        console.log(Date.now())  // 1659540040487 毫秒数
        
      • 注意:
        • 没有 实例化
        • ⚠ 只能得到 当前的 时间戳
  • 时间转换公式
    • 通过 时间戳 得到是 毫秒,需要转换为秒在计算
    • 转换公式:
      • days: d = parseInt(总秒数 / 60 / 60 / 24)
      • hours: h = parseInt(总秒数 / 60 / 60 % 24)
      • minutes: m = parseInt(总秒数 / 60 % 60)
      • seconds: s = parseInt(总秒数 % 60)
  • 倒计时函数:
    const element = document.qurySelector('css选择器')
    function getCountTime(time) {
      // 得到当前的时间戳(毫秒)
      const now = +new Date()
      // 得到未来时间时间戳(毫秒)
      const last = +new Date(time)
      // 得到剩余的时间戳(毫秒) 并转换为 秒
      const count = (last - now) / 1000
      // 将 剩余秒数 -> 天、时、分、秒
      let day = parseInt(count / 60 / 60 / 24)
      let hours = parseInt(count / 60 /60 % 24)
      // 补0
      hours = hours < 10 ? '0' + hours : hours
      let minutes = parseInt(count / 60 % 60)
      // 补0
      minutes = minutes < 10 ? '0' + minutes : minutes
      let seconds = parseInt(count % 60)
      // 补0
      seconds = seconds < 10 ? '0' + seconds : seconds
      return `${day} 天 - ${hours}:${minutes}:${seconds}`
    }
    
    function getRemainingTime(element, time) {
      // 先执行一次:定时器过1s再去执行,会有1s的显示空白时间,让它限制性,填补空白,再让后面的覆盖
      element.innerHTML = getCountTime(time)
      setInterval(function () {
          element.innerHTML = getCountTime(time)
          }, 1000)
    }
    
    getRemainingTime(div, '2022-10-1 00:00:00')
    

五、❗❗ 节点操作

  • 浏览器 使用 对象记录 网页内容
    • 浏览器把网页内容翻译成一个个的对象,把 网页内容 的 特征 翻译成 对象 的 属性
    • 这个对象就称为 DOM对象
    • 网页内容的特征:
      • 标签属性
      • 标签内容
      • 标签上下级
  • 网页内容 、对象
    • 网页内容: 标签、文本、注释
    • DOM对象:标签(元素)节点、文本节点、注释节点
    • 网页内容 和 DOM对象 一 一 对应
  • DOM树
    • 每个DOM对象中都有表示层级关系的属性,这些属性把所有DOM对象联系在一起,形成一个树状结构,称为DOM树
    • DOM树 === 网页

5.1 DOM节点

  • DOM节点: DOM树 里面 每一个内容 都称之为 节点
  • 节点类型:
    • 1️⃣ ❗✔元素节点:
      • 所有的 标签
      • html根节点
    • 2️⃣ 属性节点:
      • 所有的属性
    • 3️⃣ 文本节点:
      • 所有的文本
  • image-20220725201648559

5.2 查找节点 - 属性

  • 有效返回值 是一个 对象
  • 无效返回值 - null

5.2.1 父节点

  • 1️⃣ parentNode属性
    • 语法:
      子元素.parentNode
      
    • 返回值:
      • DOM对象
      • 最近一级 的父节点(亲爸爸),找不到 返回 null
    • 代码展示:
      <div class="yeye">
          <div class="dad">
              <div class="baby">x</div>
          </div>
      </div>
      
      <script>
          const baby = document.querySelector('.baby')
          console.dir(bady)		// div.bady -> DOM对象
          console.dir(baby.parentNode)	// div.dad -> DOM对象
          console.dir(baby.parentNode.parentNode)	  // div.yeye -> DOM对象
      </script>
      
    • 关闭广告:
      <!DOCTYPE html>
      <html lang="en">
      
      <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <style>
          .box {
            position: relative;
            width: 1000px;
            height: 200px;
            background-color: pink;
            margin: 100px auto;
            text-align: center;
            font-size: 50px;
            line-height: 200px;
            font-weight: 700;
          }
      
          .box1 {
            position: absolute;
            right: 20px;
            top: 10px;
            width: 20px;
            height: 20px;
            background-color: skyblue;
            text-align: center;
            line-height: 20px;
            font-size: 16px;
            cursor: pointer;
          }
        </style>
      </head>
      
      <body>
        <div class="box">
          我是广告
          <div class="box1">X</div>
        </div>
        <div class="box">
          我是广告
          <div class="box1">X</div>
        </div>
        <div class="box">
          我是广告
          <div class="box1">X</div>
        </div>
      
        <script>
          // const smallBox = document.querySelectorAll('.box1')
          /* for (let i = 0; i < smallBox.length; i++) {
            smallBox[i].addEventListener('click', function () {
              this.parentNode.style.display = 'none'
            })
          } */
      
          // 事件委托
          document.body.addEventListener('click', function (e) {
            if (e.target.className === 'box1') {
              e.target.parentNode.style.display = 'none'
            }
          })
        </script>
      </body>
      
      </html>
      

5.2.2 子节点

  • 1️⃣ ❌childNodes 属性
    • 语法:
      父元素.childNodes
      
    • 返回值: 获得 所有子节点、包括文本节点(空格、行换)、注释节点等
  • 2️⃣ ⚠🔻 children 属性
    • 语法:
      父元素.children
      
    • ⚠ 返回值: 伪数组 (要想得到里面的每一个节点还是要遍历
    • 注意:
      • 仅获得 所有 元素节点(标签)
      • 只选亲儿子,只不过是把亲儿子里面包含的所有节点(元素、文本、注释…)拿过来
    • 代码展示:
      <ul>
         <li>
              1
              <p>6</p>
              <span>7</span>
          </li>
          <li>2</li>
          <li>3</li>
          <li>4</li>
          <li>5</li>
      </ul>
      
      <script>
        // 获取子节点
        // 语法:父元素.children
        // 返回值:伪数组
        // 仅 获得 所有 元素节点(标签)
        console.log(document.querySelector('ul').children);
      	// 得到的是一个伪数组
      </script>
      
image-20220804225759139

5.2.3 兄弟节点

  • 1️⃣ 下一个 兄弟节点
    • nextElementSibling 属性
    • 语法:
      兄弟元素.nextElementSibling
      
    • 返回值:
      • 有下一个兄弟节点,得到的就是下一个元素
      • 没有 就是 null
  • 2️⃣ 上一个 兄弟节点
    • previousElementSibling 属性
    • 语法:
      兄弟元素.previousElementSibling
      
    • 返回值:
      • 有上一个兄弟节点,得到就是上一个元素
      • 没有 就是 null
  • 代码展示:
    <ul>
      <li>
          1
          <p>6</p>
          <span>7</span>
      </li>
      <li>2</li>
      <li>3</li>
      <li>4</li>
      <li>5</li>
    </ul>
    
    <script>
      // 上一个兄弟节点
      // 语法:兄弟元素.previousElementSibling
      // 下一个兄弟节点
      // 语法:兄弟元素.nextElementSibling
      console.log(document.querySelector('ul li:nth-child(2)').nextElementSibling)
    </script>
    
    image-20220804232438001

5.3 增加节点

  • 创建 追加

5.3.1 创建节点

  • 语法:
    document.createElement('标签名')		// 文档.创建元素
    
    • 创建的节点是一个正常的DOM对象
    • ⚠ 注意:
      document.createElement()  --  创建的是空标签
      

5.3.2 追加节点

  • 1️⃣ 插入到 父元素最后一个 子元素
    • 语法:
      父元素.appendChild(要插入的元素)	// 追加孩子
      
    • 注意: 做为 父元素 里面最后一个 子元素
    • 代码展示:⬇
  • 2️⃣ 插入到 父元素某个子元素前面
    • 语法:
      父元素.insertBefore(要插入的元素, 在哪个元素前面)	// 插入在…之前
      
    • 注意: 插入到 父元素 里面指定位置
    • 代码展示:⬇
  • 注意: appendChildinsertBefore 如果插入的是页面上 已经存在 的标签,会有 剪切 效果(将已经存在的元素 从 原位置 剪切到 新位置)
  • 代码展示:
    <style>
        div,
        li {
          font-size: 20px;
          text-align: center;
          line-height: 50px;
        }
    
        li:first-child {
          width: 150px;
          height: 50px;
          background-color: #b8f0e8;
        }
    
        li:last-child {
          width: 150px;
          height: 50px;
          background-color: #a6a6db;
        }
    
        div {
          width: 150px;
          height: 50px;
          background-color: #c0bfbf;
        }
    </style>
    
    <body>
      <ul>
        <li>我是老大</li>
      </ul>
    
      <script>
        // 增加节点(节点 -> 元素节点)
        //  1.创建节点
        //    语法:document.createElement('标签名称')
        //  2.插入节点
        //    (1).作为父元素里面的最后一个子元素
        //        语法:父元素.appendChild(要插入的元素)
        //    (2).插入到父元素里面指定位置(插入到父元素里面某个子元素的前面)
        //        语法:父元素.insertBefore(要插入的元素, 在那个子元素前面)
    
        // 1.创建节点
        const li = document.createElement('li')
        li.innerHTML = '我是老二'
        // 2.插入节点
        //    2.1获取父元素
        const ul = document.querySelector('ul')
        //    2.2作为父元素里面的最后一个子元素
        ul.appendChild(li)
    
        // 1.创建节点
        const div = document.createElement('div')
        div.innerHTML = '我是老大的大哥'
        // 2.插入节点
        //    2.1获取父元素
        const body = document.body
        //    2.2插入到父元素指定位置(插入到父元素里面指定元素前面)
        body.insertBefore(div, ul)
        // 将创建的节点始终插入到父元素的最前面
        /*
          body.children  // 包含body下所有的(亲)子节点伪数组
        	body.insertBefore(div, body.children[0])
        */
      </script>
    </body>
    
    image-20220805002046014

5.3.3 克隆节点

  • 特殊情况 的 新增节点
  • 应用场景:轮播图
  • 步骤:
    • 1️⃣ 复制 一个 原有节点
    • 2️⃣ 把 复制的节点 放入到 指定元素内部
  • 语法:
    元素.cloneNode(布尔值)
    
    • clondNode会克隆出一个跟原标签一样的标签(原标签上面有什么,克隆后的标签上面就有什么)(是两个元素,克隆成功后前后两个元素没有任何关系)
    • 参数:
      • true - 深克隆: 克隆时 包含 后代节点 一起克隆 (节点 -> 文本节点、注释节点等所有的节点)
      • false - 浅克隆: 克隆时 不包含 后代节点、
      • 默认值false
    • 代码展示:
      <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
      </ul>
      
      <script>
          const ul = document.querySelector('ul')
          // const newLi = ul.children[0].cloneNode(true)
          // newLi.innerHTML = 'newLi'
          // ul.appendChild(newLi)
          ul.insertBefore(ul.children[0].cloneNode(true), ul.children[11])
      </script>
      

5.4 删除节点

  • 在 JavaScript 原生DOM操作中,要 删除元素 ⚠ 必须 通过 父元素 删除
  • 语法:
    父元素.removeChild(要删除的元素)
    
  • 注意:
    • 如果 不存在 父子关系 则 删除 不成功
    • 删除节点 和 隐藏节点(display: none;)有区别
      • 删除节点:从DOM中删除节点
      • 隐藏节点:只是在页面上不显示,DOM节点依然存在
  • 补充:
    • 语法: 自杀式z
      删除的元素.remove()
      
  • 拓展:
    • 替换节点:
    • 语法:
      parentNode.replaceChild(newChild, oldChild);
      
    • 方法用指定的节点替换当前节点的一个子节点,并返回被替换掉的节点
  • 重绘 和 回流
    • 重绘: 由于节点(元素)样式的改变并不会影响它在文档流中的位置和文档布局时,则是重绘
    • 回流: 元素的尺寸、结构、布局等发生变化时,浏览器就会重新渲染部分或全部文档的过程称为回流
    • 重绘不一定一起回流,但回流一定会引起重绘
    • 简单理解,影响到了布局,就会有回流

六、❌ M端事件

  • 常见的触屏事件(touch)
  • 触屏 touch 事件说明
    touchstart手指 触摸 到一个DOM元素时触发
    touchmove手指在一个DOM元素上 滑动 时触发
    touchend手指从一个DOM元素上 移开 时触发

七、❗ JS插件

  • 熟悉官网,了解这个插件可以完成什么需求 https://www.swiper.com.cn/
  • 看在线演示,找到符合自己需求的demo https://www.swiper.com.cn/demo/index.html
  • 查看基本使用流程 https://www.swiper.com.cn/usage/index.html
  • 查看APi文档,去配置自己的插件 https://www.swiper.com.cn/api/index.html
  • 注意: 多个swiper同时使用的时候, 类名需要注意区分
  • 使用步骤:
    • 引入资源
      • css文件
      • js文件
    • 导入代码
      • 复制html结构
      • 复制css样式
      • 复制js行为

八、❗❗ window对象

window(JS中的顶级对象) > BOM(浏览器对象模型) > DOM(页面文档对象模型)

8.1 BOM(浏览器对象模型)

  • BOM(Browser Object Model)- 浏览器对象模型
    • 由一些列相关的对象构成,并且每个对象都提供了很多方法和属性
    • 浏览器的内容被翻译成了对象
  • image-20220807205819018
  • window 对象是一个 全局对象,也可以说是 JavaScript 中的 顶级对象
  • 像document、alert()、console.log()这些都是window的属性,基本BOM的属性和方法都是window的
  • ⚠ 所有通过 var 定义在 全局作用域 中的 变量函数 都会变成 window对象属性方法
  • ⚠ window对象下的属性和方法调用的时候可以 省略window
  • DOM 和 BOM 区别:
    • image-20220912145005712

8.2 定时器 - 延时函数

  • 定时器 = 间歇函数(setInterval()) + 延时函数(setTimeout())
  • 让代码 延迟 执行的函数 - setTimeout()
  • 语法:
    setTimeout(回调函数, 等待的毫秒数)
    
  • 清除延时函数:
    let timerId = serTimeout(回调函数, 等待的毫秒数)
    clearTimeout(timerId)
    
  • 注意:
    • setTimeout 仅仅 只执行 一次 ,平时省略 window
    • 延时函数需要等待,所以后面的代码先执行
    • 每一次调用延时器都会 产生一个 新的 延时器
  • 间歇函数 和 延时函数 的区别:
    • 间歇函数:每隔一段时间就执行一次,除非手动清除
    • 延时函数:执行一次

8.3 JS执行机制

  • JS代码 从上到下 执行
  • 单线程: 同一时间只能做一件事
    • 所有的任务需要排队,前一个任务结束,才会执行后一个任务

8.3.1 同步 与 异步

  • 1️⃣ 同步
    • 前一个任务结束后再执行后一个任务,程序的执行顺序任务的排列顺序一致的
    • 同步任务: 都在 主线程 执行栈 上执行
  • 2️⃣ 异步
    • 如果执行一个任务需要花费一定的时间,在执行这个任务的同时可以去执行别的任务
    • 耗时 的都是 异步
    • JS的 异步 是通过 回调函数 实现的
    • 异步任务的三种类型
      • 普通事件(click、mouseenter、mouseleave、……)
      • 资源加载
      • 定时器 (间歇函数(setInterval) + 延时函数(setTimeout))
    • 异步任务 添加到 任务队列 (消息队列)中
  • 同步异步本质 区别:
    • 一条流水线上的 各个流程 执行顺序不同
  • 3️⃣ 执行机制:
    • ① 先执行 任务栈 中的 同步任务
    • 异步任务 添加到 任务队列 里面
      • 异步任务 进行 排序(根据每个异步任务所消耗的时间 )
    • ③ 一旦 执行栈 里面的 所有 同步任务 执行完毕系统 就会 按次序 读取 任务队列 中的 异步任务,于是 被读取异步任务 结束 等待状态进入 执行栈,开始执行。
    • image-20220808142927967

8.3.2 事件循环 - event loop

  • image-20220808144521013
  • 由于 主线程 不断的 重复 获得任务、执行任务、再获取任务、再执行,所以这种机制被称为 事件循环(enevt loop)
  • 事件循环: js执行代码时,会把同步任务添加到主线程执行栈中执行,把满足条件的异步任务推到任务队列排队等候执行,事件循环是一种轮询机制,当执行栈中的所有同步任务执行完毕之后,系统就会依次读取任务队列中的异步任务,异步任务结束等待状态,按照次序添加到执行栈中执行。

8.4 location 对象

  • location数据类型对象,它 拆分保存URL地址各个 组成 部分
  • 常用 属性 和 方法:
    • 1️⃣ ✔🔺 href: 属性 获取 完整的URL地址,对其 赋值时 用于 地址的跳转
      • const btn = document.querySelector('button');
        btn.addEventListener('click', function () {
            location.href = 'https://www.baidu.com';
        });
        
      • 可以后退
    • 2️⃣ search: 属性 获取地址中 携带的参数,符号 ? 后面部分
      • console.log(location.search); 	// 字符串
        
    • 3️⃣ hash: 属性 获取地址中的 哈希值,符号 # 后面部分
      • console.log(location.hash);		// 字符串
        
    • 4️⃣ reload(是否使用缓存): 方法 用来 刷新 当前 新页面,传入参数 true 时表示 强制刷新,默认false使用缓存刷新
      • const btn = document.querySelector('.reload');
        btn.addEventListener('click', function () {
          // F5 -> 刷新
          //location.reload();
          // F5+Ctrl -> 强制刷新  
          location.reload(true);
        });
        
    • 5️⃣ replace(): 方法 页面跳转(覆盖旧地址)
      • const btn = document.querySelector('button');
        btn.addEventListener('click', function () {
            location.replace('https://www.baidu.com');
        });
        
    • href属性replace()方法 实现页面跳转的区别:
      • href属性: 保留 原地址具有回退功能
      • replace()方法: 覆盖 原地址没有回退功能

8.5 navigator 对象

  • navigator数据类型对象,该对象记录了 浏览器 自身的 相关信息
  • 常用 属性 和 方法:
    • 浏览器相关信息:navigator.userAgent
    • 通过 userAgent 检测 浏览器版本平台
      // 检测userAgent(浏览器信息)
      !(function () {
        const userAgent = navigator.userAgent;
        // 验证是否为Android或iPhone
        const android = userAgent.match(/(Android);?[\s\/]+([\d.]+)?/);
        const iphone = userAgent.match(/(iPhone\sOS)\s([\d_]+)/);
        // 如果是Android或iPhone,则跳转至移动站点
        if (android || iphone) {
          location.href = 'http://m.itcast.cn';
        }
      })();
      

8.6 history 对象

  • histroy数据类型对象,主要管理历史记录,该对象与浏览器地址栏的操作相对应。
  • 常用属性和方法:
    • back(): 可以 后退 功能
    • forward(): 前进 功能
    • go(参数): 前进 后退 功能
      • 参数:
        • 1: 前进 一个页面 (back())
        • 0: 刷新页面(使用缓存刷新) (reload())
        • -1: 后退 一个页面 (forward())
    • 代码展示:
      <button>后退</button>
      <button>前进</button>
      <script>
          // 获取元素
          const back = document.querySelector('button');
          const forward = back.nextElementSibling;
          // 事件侦听-点击事件
          back.addEventListener('click', function () {
          // 前进一步
          history.go(1);
          });
          forward.addEventListener('click', function () {
          // 后退一步
          history.go(-1);
          });
      </script>
      

九、❗❗ 本地存储

  • 数据存储 在 用户 浏览器 中(硬盘)
  • 设置、读取方便、甚至 页面刷新 不会丢失 数据
  • 容量较大、sessionStprangelocalStorage 约5M
  • 为什么要将数据存储到本地存储里?
    • 数据持久化(数据不丢失)

9.1 本地存储分类

9.1.1 localStorage

  • 作用: 可以 将 数据 永久存储本地(用户电脑),除非手动清除,否则关闭页面 也会 存在
  • 生命周期: 什么时候失效,什么时候死掉
  • 特性:
    • 可以多窗口(页面)共享同一浏览器可以共享)(不能跨域(同一个域名)使用)
    • 键值对 的形式 存储使用
  • ⚠🔻 语法:
    • 1️⃣ 存储/修改 数据:
      localStorage.setItem(key, value)		
      // 设置每个小项,key和value要加引号,key和value可以是变量
      
      • 这个键就是 修改没有 就是 添加
      • 代码展示:
        // 本地存储 - localStorage
        // 存储数据 - localStorage.setItem(key, value);
        // 要加引号
        localStorage.setItem('uname', '邵秋华');
        
        image-20220809085436994
    • 2️⃣ 获取 数据:
      localStorage.getItem(key)			// 获取里面的项,key必须加引号
      
      • 返回值:
        • 有这个key,就返回对应的值
        • 没有这个key,返回 null
      • 代码展示:
        // 获取数据 - localStorage.getItem(key)
        // 要加引号
        console.log(localStorage.getItem('uname'));	// 邵秋华
        
    • 3️⃣ 删除 某项数据:
      localStorage.removeItem(key)		// 移除里面的项, key必须加引号
      
      • 代码展示:
        // 删除本地存储
        localStorage.removeItem('uname');
        
    • 4️⃣ 清空 数据:
      localStorage.clear()
      
      • 慎用
      • 清空全部数据
  • ⚠⚠ 注意:
    • ⚠ 所有的 必须加 引号
    • 有这个键就是修改,没有就是添加
    • ⚠🔺 本地存储 只能存储 字符串 类型的数据
    • 得到的值也是字符串型
    • 如果value写的是数值型,存的时候会转换成字符型
    • 代码展示:
      const arr = [1, 2, 3, 4];
      arr.forEach((item, index) => {
        localStorage.setItem(`id:${index}`, item);
        console.log(localStorage.getItem(`id:${index}`));	// 1 2 3 4(字符串)
        console.log(typeof (localStorage.getItem(`id:${index}`)));// string
      });
      

9.1.2 sessionStprange

  • 特性:
    • 生命周期关闭浏览器窗口
    • 同一个窗口(页面)下 数据可以共享
    • 键值对 的形式 使用
    • 用法跟localStorage基本相同
  • localStoragesessionStorage 的区别
    • 他们的 作用 相同,但是 存储方式 不同,因此应用场景也不同
    • localStorage 的数据可以 长期存储关闭浏览器 数据不会消失,除非 手动清除
    • sessionStorage 的数据时是 临时存储页面被关闭,存储在sessionStorage里的 数据 会被 清除

9.2 存储复杂数据类型

  • 本地存储 只能存储 字符串,不能存储 复杂数据类型
  • JSON:
    • 属性和值都有引号,而且是双引号
    • 一种字符串格式的名称
    • 把 数组/对象 转换为结构为 ”数组/对象“ 的字符串
    • 只能存:数字、字符串、对项
    • 不能存null、undefined、函数
    • ⚠ JSON.parse(转换数据):要转换的数据不是JSON格式的字符串image-20220815085625050
  • 存储复杂数据类型步骤:
    • 1️⃣ 将 复杂数据类型JSON字符串
      • 语法:
        JSON.stringify(复杂数据类型)
        
      • 代码展示:
        // 本地存储只能存储字符串,不能存储复杂数据类型
        // 如果要存储复杂数据类型,需要将复杂数据类型转换成 JSON 字符串
        // 语法:JSON.stringify(复杂数据类型);
        let obj = {
          uname: '邵秋华',
          age: 22,
          gender: '男',
        };
        
        localStorage.setItem('obj', JSON.stringify(obj));
        
        image-20220809093054731
    • 2️⃣ 将 JSON字符串复杂数据类型
      • 语法:
        JSON.parse(JSON字符串)
        
      • 代码展示:
        console.log(JSON.parse(localStorage.getItem('obj')));
        
        image-20220809094516421
  • 存:
    • 复杂数据类型 -> JSON.stringify() -> JSON字符串 -> 存到本地存储中
  • 取:
    • 从本地存储中取 -> JSON字符串 -> JSON.parse() -> 复杂数据类型

十、❗ 正则表达式

  • 正则表达式(Reular Expression):用于 匹配 🔺字符串🔺 中 字符组合模式
    • JavaScript 中,正则表达式 也是 对象(object )
    • ⚠🔺 注意: 只能对 字符串 进行匹配
  • 正则表达式的作用
    • 1️⃣ 表单验证(匹配
    • 2️⃣ 过滤敏感词汇(替换
    • 3️⃣ 字符串中提取我们想要的部分(提取 ->-爬虫)

10.1 正则表达式的使用

  • 1️⃣ 定义规则:
    • 语法:
      const regObj = /表达式/	// 正则表达式不改变使用
      
      const regObj = new RegExp('表达式')	// 正则表达式变化使用
      
    • 注意:
      • // 正则表达式 的 字面量
      • // 中间写什么,就查找什么
      • ⚠🔺 // 中间 不要乱加 空格
      • 只要涉及到正则表达式不要乱加空格,最好用vs格式化
  • 2️⃣ ✔检测查找是否匹配:
    • 语法:
      • test() :用来 查看 正则表达式指定的字符串 是否匹配
      • regObj.test(被检测的字符串)
        
    • 返回值:
      • 匹配true
      • 不匹配false
      • 规则在前面,被检测的就是用户输入的内容
    • 注意:
  • 代码展示:
    // 正则表达式
    // 正则表达式使用
    // 1)定义规则
    //    语法:const 变量名(regObj) = /表达式/;
    //    注意:正则表达式的字面量中间 不要乱加空格
    //    字面量中间些什么就匹配什么(不要乱加空格)
    // 2)是否匹配
    //    语法:regObj(字面量).test(被检测的字符串);
    	const reg = /前端/;
    	const str = '我在学习前端,希望学完高薪就业!!!';
    	console.log(reg.test(str));		// true
    
    // 注意
    	const reg = / 前端 /;
    	const str = '我在学习前端,希望学完高薪就业!!!';
    	console.log(reg.test(str));		// false
    
    // 注意
    	console.log(//.test('哈'));		// true
    	console.log(//.test('哈哈'));	// true
    	console.log(//.test('二哈'));	// true
    
  • 3️⃣ ⭕检索符合规则的字符串:
    • 语法:
      • exec():在一个 指定字符串 中执行一个 搜索匹配
      • regObj.exec(被检测字符串)
        
    • 返回值:
      • 匹配数组
      • 不匹配null
  • 代码展示:
    const reg = /前端/;
    const str = '我在学习前端,希望学完高薪就业!!!';
    console.log(reg.exec(str));	
    
    image-20220809181458176
  • 正则表达式检测查找 test()方法 和 exec()方法 有什么区别?
    • text(): 用于判断是否有符合规则的字符串,返回的是一个布尔值,找到 返回 true没找到 返回 false
    • exec(): 用于检索(查找)符合规格的字符串,找到 返回 数组没找到null

10.2 ❗ 元字符

  • 字符
    • 普通字符
      • 大多数的字符仅能够描述它们本身(字母数字)
      • 普通字符 只能够 匹配 字符串中 与 它们 相同的字符
    • 元字符
      • 是一些 具有 特殊含义 的 字符
      • 优点: 极大提高了 灵活性 和 强大的匹配功能
  • ⚠🔻 边界符、量词、字符类 组合使用
  • 1️⃣ 边界符
    • 表示位置,开头和结尾,必须用什么开头,用什么结尾
    • 用来提示字符所处的位置
      • 边界符说明
        ^表示匹配 行首 的文本(以谁开始
        $表示匹配 行尾 的文本(以谁结束
      • 注意:
        • ^ $ 在一起,表示 必须是 精确匹配
      • 代码展示:
        console.log(//.test('哈'));		// true	// 字符串的内容 和 规则相等
        console.log(//.test('哈哈'));	// true
        console.log(//.test('二哈'));	// true
        
        console.log(/^哈/.test('哈'));	// true
        console.log(/^哈/.test('哈哈'));	// true
        console.log(/^哈/.test('二哈'));	// flase
        
        console.log(/^哈$/.test('哈'));	   // true
        console.log(/^哈$/.test('哈哈'));  // false -- 精确匹配(字符串的内容、长度必须和规则相等)
        console.log(/^哈$/.test('二哈'));  // flase
        
  • 2️⃣ 量词
    • 表示重复次数
    • 设定 某个模式出现 次数
    • 量词说明
      *****重复 零次多次 >= 0
      +重复 一次多次 >=1
      ?重复 零次一次
      {n}重复 n次
      {n,}重复 n次更多次 >= n
      {n,m}重复 n 到 m 次 n <= 次数 <= m
      • ⚠🔺注意:
        • 🔺n,m🔻 之间 🔺没有空格🔻
        • 离量词 最近的(量词的左边) 重复,别的不重复
  • 3️⃣ 字符类
    • [] - 匹配字符集合
      • 被检测的数据 只要能和 规则 匹配到 任意🔺一个🔻字符 就是 true,否则就是false
      • 代码展示:
        后面的字符串只要包含abc中任意一个字符,都返回true
        console.log(/[abc]/.test('andy'));  // true
        console.log(/[abc]/.test('baby'));  // true
        console.log(/[abc]/.test('cry'));   // true
        console.log(/[abc]/.test('die'));   // false
        
      • 精确匹配: 被检测的数据 🔺只能🔻 和 规则 匹配 🔺一个🔻 字符(n选1),要想多个匹配须和量词配合使用
        console.log(/^[abc]$/.test('a'));	  // true
        console.log(/^[abc]$/.test('b'));	  // true
        console.log(/^[abc]$/.test('c'));	  // true
        console.log(/^[abc]$/.test('ab'));	// false
        console.log(/^[abc]{1,}$/.test('abc'));	// true
        
    • - 连字符
      • 使用连字符 - 表示一个 范围
      • [a-z] : 表示 a~z 26个英文字母都可以
      • [a-zA-Z] : 表示大小写都可以
      • [0-9] : 表示 0~9 都可以
      • [\u4e00-\u9fa5] 匹配汉字
        
      • 代码展示:
        /^[1-9][0-9]{4,}$/	// 第一个数字:1~9;从第二位开始:0~9;可以重复>=4
        
    • ^ - 取反符号
      • [] 加上 ^ 取反符号
      • [^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]
        • 日期:^\d{4}-\d{1,2}-\d{1,2}$
          
    • () 使用小括号将字符包成一个整体
    • |
  • 特殊符号写到 [] 里的最后面

10.3 修饰符

  • 修饰符 约束 正则表达式的某细节 行为 ,如是否区分大小写、是否支持多行匹配
  • 语法:
    /表达式/修饰符
    
    • i: (ignore)正则匹配时 不区分 大小写
    • g: (global)匹配 所有 满足正则表达式结果 (全局匹配)
    • m: 执行多行匹配
    • 代码展示:⬇
  • replace - 替换
    • 语法:
      字符串.replace(/正则表达式/, '替换文本')
      
    • 返回值: 替换好的字符串
    • 代码展示:⬇
    • 替换多个:
      字符串.replace(/正则表达式/g, '替换文本')
      
      • 代码展示:⬇
    • 替换多个 并且 不区分大小写:
      字符串.replace(/正则表达式/ig, '替换文本')
      字符串.replace(/正则表达式/gi, '替换文本')
      
      • ⚠🔺 g i 不区分 前后
      • 代码展示:⬇
    • 替换多个 并且 不区分大小写:(用正则表达式里面的
      字符串.replace(/正则表达式|正则表达式/, '替换文本')
      
      • ⚠🔺 或(|) 两侧 不要加 空格
      • 如果没有小括号,就是将正则表达式分成多份
      • 代码展示:⬇
    • 代码展示:
      // 修饰符:约束正则表达式的细节行为
      // 语法: /正则表达式/修饰符
      // i(不区分大小写) + g(匹配所有满足正则表达式的结果)
      // i
      console.log(/^java$/.test('JAVA'));   // false
      console.log(/^java$/i.test('JAVA'));  // true
      console.log(/^java$/i.test('JavA'));  // true
      
      // 替换 - replace
      // 语法:字符串.replace(/正则表达式/, '替换文本')
      const str = 'java是一门编程语言,学完JAVA工资很高';
      
      // 替换一个
      const re1 = str.replace(/java/, '前端');
      console.log(re1);		// '前端是一门编程语言,学完JAVA工资很高'
      
      // 替换多个 - g
      const re2 = str.replace(/java/ig, '前端');
      console.log(re2);		// '前端是一门编程语言,学完前端工资很高'
      
      // 替换多个 - 或(|) (正则表达式里的或)(|两侧不要加空格)
      const re3 = str.replace(/java|JAVA/g, '前端');
      console.log(re3);		// '前端是一门编程语言,学完前端工资很高'
      
  • 拓展:
    • change - 事件
      • 当鼠标离开表单,并且表单值发生变化触发

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/512971.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

idm下载器2024官方最新中文版免费下载

哈喽大家好呀&#xff0c;coco玛奇朵发现我已经有一阵子没有给大家分享windows软件了&#xff0c;今天给大家分享一款暗藏惊喜的windows软件&#xff0c;用过之后真的很难拒绝&#xff01; 这是一个可以帮你提升下载速度的工具&#xff0c;有了它几秒就能帮你下载好各种资源。…

UNIAPP实战项目笔记64 当前用户修改收货地址的前端和后端

UNIAPP实战项目笔记64 当前用户修改收货地址的前端和后端 思路 默认地址的修改&#xff0c;先清空当前id下的所有默认地址&#xff0c;再将新地址设为默认 前端 将新值传给后端 后端接受值后更新处理 实例截图 代码 后端 index.js var express require(express); var route…

大数据Doris(十六):分桶Bucket和分区、分桶数量和数据量的建议

文章目录 分桶Bucket和分区、分桶数量和数据量的建议 一、分桶Bucket

机器学习随记(6)—K-means

1 K-means方案 K-means 算法是一种自动将相似数据点聚集在一起的方法。 具体来说&#xff0c;你得到了一个训练集{,...,}&#xff0c;并且您希望将数据分组为几个有凝聚力的“集群”。 K-means 是一个迭代过程 首先猜测初始质心&#xff0c;然后改进这个猜测 反复将样本分配到…

Seurat -- Cluster the cells --第一部分

文章目录 briefKNN&#xff08;k-nearest neighbor&#xff09;简介部分SNN&#xff08;shared nearest neighbor&#xff09;简介部分Annoy算法理解Jaccard indexSeurat进行聚类的步骤可视化部分subcluster之间的marker gene具体参数 brief seurat 官方教程的解释如下&#x…

Hash碰撞

Hash碰撞 什么是Hash碰撞 Hash碰撞是指两个不同的输入值&#xff0c;经过哈希函数的处理后&#xff0c;得到相同的输出值&#xff0c;这种情况被称之为哈希碰撞。 例如&#xff1a;两个不同的对象&#xff08;object1和object2的值&#xff09;经过Hash函数计算后的&#xf…

科思转债上市价格预测

科思转债 基本信息 转债名称&#xff1a;科思转债&#xff0c;评级&#xff1a;AA-&#xff0c;发行规模&#xff1a;7.249178亿元。 正股名称&#xff1a;科思股份&#xff0c;今日收盘价&#xff1a;67.1元&#xff0c;转股价格&#xff1a;53.03元。 当前转股价值 转债面值…

【进程间通信 之 通信的建立】

目录&#xff1a; 前言进程间通信的目的进程间通信的方式管道1.匿名管道简单示例1 - 消息传输五个特性四种场景简单示例2 - 进程控制对管道的深入理解 2.命名管道简单示例3 -- 不相关进程间通信 system V共享内存简单示例4 - 通知事件消息传输 总结 前言 打怪升级&#xff1a;…

后摩尔时代 , 从有源相控阵天线走向天线阵列微系统

本文围绕高分辨率对地微波成像雷达对天线高效率、低剖面和轻量化的迫切需求 , 分析研究了有源阵列天线的特点、现状、趋势和瓶颈技术 , 针对对集成电路后摩尔时代的发展预测 , 提出了天线阵列微系统概念、内涵和若干前沿科学技术问题 , 分析讨论了天线阵列微系统所涉及的微纳尺…

完全集成的云备份和还原服务——NetApp Cloud Backup

完全集成的云备份和还原服务 NetApp Cloud Backup 提供无缝且经济高效的备份和还原功能&#xff0c;用于保护和归档云端和内部 ONTAP 数据。 为什么选择 NetApp Cloud Backup&#xff1f; 可轻松保护云端和内部 ONTAP 数据 NetApp Cloud Backup 提供无缝且经济高效的备份和还…

科大讯飞星火认知大模型怎么样?

“鉴于SparkDesk服务目前处于内部用户体验阶段&#xff0c;所有与SparkDesk相关的交互内容、技术参数等信息均被视为保密信息。您了解并同意&#xff0c;且有责任对这些保密信息严格保密&#xff0c;您不得以任何方式&#xff08;包括但不限于截图、录屏、拍照等&#xff09;披…

Linux shell编程常用命令(sort排序 uniq重复行 set +-x调试脚本 tr压缩替换字符 cut切片)

sort命令 排序 以行为单位对文件内容进行排序&#xff0c;也可以根据不同的数据类型来排序 比较原则是从首字符向后&#xff0c;依次按ASCII码值进行比较&#xff0c;最后将他们按升序输出。 sort [选项] 参数 cat file | sort 选项-n 按照数字进行排序 -r 反向排序 -u 等同于u…

【源码解析】SpringBoot整合AOP原理解析

AOP介绍 AOP&#xff08;Aspect Oriented Programming&#xff09;是基于切面编程的&#xff0c;可无侵入的在原本功能的切面层添加自定义代码&#xff0c;一般用于日志收集、权限认证等场景。 AOP基本概念 通知&#xff08;Advice&#xff09;: AOP 框架中的增强处理。通知…

L1:提示工程的关键原则

提示工程指南&#xff1a;关键原则 一、 环境配置 chatgpt使用有诸多限制&#xff0c;所以采用国产模型来代替&#xff0c;加载开源的chatGLM模型&#xff0c;使用ChatGLM-6b的INT8版本。 chatGLM6b在LLM匿名竞技场中的排名&#xff1a; import os import torch import war…

[学习笔记] [机器学习] 4. [下]线性回归(正规方程、梯度下降、岭回归)

6. 梯度下降和正规方程的对比 问题梯度下降正规方程学习率需要选择合适的学习率不需要求解特点需要多次迭代求解一次运算得出线性问题可以解决可以解决非线性问题可以解决不可以解决时间复杂度难以直接给出的&#xff08;受到初始值、学习率、迭代次数等多种因素的影响&#x…

学生如何使用chatGTP提升学习能力?

短短两三个月&#xff0c;ChatGPT炸圈范围越来越大&#xff0c;很快就从科技圈来到了教育界。前段时间&#xff0c;北密歇根大学的哲学教授Antony Aumann在批改论文的过程中发现一篇论文好到令人感到震惊。这篇论文逻辑严谨&#xff0c;措辞得当&#xff0c;结构清晰&#xff0…

《JavaEE初阶》Tomcat

《JavaEE初阶》Tomcat 文章目录 《JavaEE初阶》TomcatTomcat是什么下载Tomcat简单介绍Tomcat的文件使用tomcat部署静态页面启动tomcat 部署代码: Tomcat是什么 在学习tomcat之前,我们已经学习了HTTP协议,我们知道HTTP协议是应用层协议. HTTP的客户端是我们的网页和浏览器,而H…

MySQL新增时实现新增或更新操作

MySQL新增时数据重复则更新或不操作&#xff0c;不重复则新增 应用场景实现方案1. REPLACE INTO 语句&#xff1a;2. INSERT INTO ... ON DUPLICATE KEY UPDATE 语句结合事务&#xff1a;3. INSERT INTO ... SELECT ... FROM ... ON DUPLICATE KEY UPDATE 语句&#xff1a;4. 根…

Kyligence一站式数字化建设的新指标

1.数字化时代中小企业的痛点与难点 数字化时代&#xff0c;众多领先企业纷纷利用数字化技术&#xff0c;实现业务精细化运营和降本增效&#xff0c;从而有效提升企业的盈利水平和竞争力。其中最重要的手段就是业务过程数据指标化&#xff0c;通过对指标的定义、监控、分析和洞…

【容器化应用程序设计和开发】2.5 容器化应用程序的安全性和合规性考虑

往期回顾&#xff1a; 第一章&#xff1a;【云原生概念和技术】 第二章&#xff1a;2.1 容器化基础知识和Docker容器 第二章&#xff1a;2.2 Dockerfile 的编写和最佳实践 第二章&#xff1a;2.3 容器编排和Kubernetes调度 第二章&#xff1a;2.4 容器网络和存储 2.5 容器…