JavaScript笔记

文章目录

1 JavaScript 简介

JS:解释型语言,不需要编译,代码的执行是从上到下一行行执行的,上一行没执行,下一行就不会执行。
BOM:操作浏览器发生变化的属性和方法
DOM:操作文档流发生变化的属性和方法
ECMScript:书写语法和书写规则

2 JS 基础

alert(num),数据出现在浏览器提示框
console.log(num),数据输出在浏览器控制台
document.write(num),以文档输出,也就是输出在浏览器的页面(body)

3 JS 代码编写位置

3.1 行内式

  • 直接把代码书写在标签上
    a 标签写法:书写在 herf 属性上
    非 a 标签:属性在行为属性上
<a href="javascript:JS代码;">一个链接</a>
<div onclick="JS代码">一个div盒子</div>

3.2 内嵌式

将 js 代码写在 script 标签里
不依赖任何行为,打开页面就执行。

<body>
    <script>
        // JS代码
    </script>
</body>

3.3 外联式

把 JS 代码写在一个. js 文件内,然后在 html 中用 script 标签的 src 属性引入对应地址的 js 文件;
script 标签一旦用于外部文件引用,内部就不能再写代码了,写了也没用,需要的话可以重新再写一个 script 标签。
不依赖任何行为,打开页面就执行。

<body>
    <script src="js文件地址"> </script>
</body>

4 基本语法

  1. 严格区分大小写
  2. 每条语句以分号结尾,不写也可以,但是浏览器会自动添加分号,降低性能,有时候还会出错,所以必须加分号
  3. 注释格式同 Java,有///* */两种
  4. 输入 text = prompt(’弹出输入框‘)
  5. 输出 console.log(’输出到控制台‘)

5 字面量和变量

5.1 字面量

都是可以直接使用的,不能改变其值

5.2 变量

var 关键字声明变量,表示请求内存,一个 var 只能保存一个值 var a = 80;

6 标识符

所有可以自主命名出来的都叫标识符
命名规则:

  1. 数字、字母、下划线、美元符号;
  2. 不能数字开头
  3. 不能和关键字、保留字重复;
  4. 一般采用驼峰命名法 xxxYyyZzz;
  5. 底层保留标识符采用的 Unicode 编码,其实其他符号也可以,但不这么用。

7 数据类型

数据类型指的是字面量的类型,js 中一共 6 种数据类型,可以使用 typeof 查看变量类型;

  1. String 字符串
    用引号引起来的字符,单双引号都可以,不要单双混用;
    想要嵌套双引号,可以使用 \ 作为转义字符,比如 " 意思是后面的内容就是文字双引号,不代表字符春,还有 \ n 换行。
    字符串可以直接相加连接,任何值和字符串相加都会转换成字符串再相加。var a = "hello";

  2. Number 数值
    js 中所有数字都是 number 类型,包括整数和浮点数。
    最大 Number.MAX_VALUE,最小 Number.MIN_VALUE,是一个正值
    溢出为 Infinity,表示正无穷,加负号就是负无穷,这是一个字面量,
    NaN 表示 not a number,也是一个字面量。

  3. Boolean 布尔值
    true 和 false var a = true;

  4. Null 空值
    Null 类型的值只有一个 null,专门用来表示空的对象,null 的 typeof 为 object

var a = null;
  1. Undefined 未定义
    Undefined 类型的值也只有一个 undefined,当声明了一个变量,但是没给它赋值时,就是这种类型;
    typeof 为 Undefined。 var a;
  2. Object 对象
    js 万物皆对象

8 强制类型转换

主要是把其他数据转换成 sring、number、boolean

8.1 其他类型转 string

  1. toString()方法
    该方法不影响原变量,null 和 undefined 没有 toString()方法

    var a = 123;
    a = a.toString(); // a = '123'
    var b = true;
    b = b.toString(); //b = 'true'
    
  2. String()函数
    null 和 undefined 也可以调用 String()函数,
    对其他类型其实也是调用 toString 方法,但是上面两种类型是直接给他们加上双引号。

    var a = 123;
    a = String(a); // a = '123'
    var a = null;
    a = String(a); // a = 'null'
    
  3. 加上空串
    任意值加上字符串都会被调用 String() 转换成字符串再连接。

    var a = 123;
    a = a + "";  // a = "123"
    

8.2 其他类型转 number

  1. Number()函数
    若字符串中有非数字字符,就会返回 NaN
    空串、纯空格串 会返回 0
    true --> 1 , false --> 0, null --> 0, undefined --> NaN

    var a = "123";
    a = Number(a); //a = 123;
    var b = "abc";
    b = Number(b); //b = NaN
    
  2. parseInt()和 parseFloat()函数
    专门针对字符串,可以将一个字符串中从第一个字符开始有效的整数 、浮点数内容取出转换。
    如果对非 String 类型使用这两个函数,会先转换成字符串,再处理。
    第一个参数为要转换的数据,第二个参数可以缺省,表示前一个参数的进制

    var a = "123aaa456";
    a = parseInt(a); // a = 123
    var b = "123.456.1aaa456";
    b = parseInt(b); // b = 123.456
    

8.3 其他类型转 Boolean

Boolean()函数,除了数字 0、空串’'、NaN、null、undefined,其他任何类型都是 true

var a = 123;
a = Boolean(a); // a = true
a = Boolean(0); // a = flase

9 其他进制数字

都会转换成 2 进制存到计算机,都会以十进制输出。

10 运算符

10.1 算数运算符 + - * / %

  • +: 当符号两边都是数字或者布尔的时候,进行数学运算;只要任意一边是字符串,就会进行字符串拼接运算。

    var a = '10',b = 20;
    var c = a + b; //c = '1020'
    
  • 其他算数运算符只能进行数学运算

10.2 赋值运算符 =、+=、-=、*=、/=

右边的值赋给左边

10.3 比较运算符 >、<、>=、<=、= =、= = =、!=、!==

  • 运算结果为布尔值
  • 两个等于号:等于,转换成 number 比较是否相等,不考虑数据类型
  • 三个等于号: 全等,要考虑数据类型
  • != 和!== 为不等于和不全等于,对应上面两种情况

10.4 逻辑运算符 &&、||、!

  • &&: 非布尔值运算时,若第一个值为 true,则直接返回第二个值的原值,若第一个值为 false,则直接返回第一个值原值
  • ||:同理,若第一个值为 false,则直接返回第二个原值,若第一个为 true,则直接返回第一个的原值
    弄清与或的判断原理就行。

10.5 自增和自减 ++ 、–

注意 a++ 和 ++a 的区别

10.6 其他运算符

  • 单目运算符:+ 正号、- 负号,可以给任意类型前面写个正号转换成 number

    var a = true;
    console.log(+a); // a = 1
    
  • 条件运算符 ?:

10.7 Unicode 编码

转义字符 \u 表示后面跟的是 Unicode 编码(四位),可以用来输出任意字符 console.log('\u1234')
在 html 中用的是 &#,后面跟的是 10 进制 Unicode 编码。

11 代码块

JS 语句是由上到下一句一句按顺序执行的,我们可以用 {} 来分组,不影响执行效果,一个 {} 称之为一个代码块

12 条件分支 - if

if(3>1)
	console.log(3);
else
	console.log(1);

13 条件分支 - swich

switch 语句,当匹配成功时,执行 case 后面的语句,而且之后不会再判断,会一直向下穿透执行直到遇到 break;
default 为所有条件都匹配失败时执行。

var a = 30;
switch(a){
    case 10 : 
        console.log(10);
        break;
    case 20 : 
        console.log(20);
        braek;
    case 30 : 
        console.log(30);
        // break;
    case 40 : 
        console.log(40);
        break;
    case 50 : 
        console.log(50);
        break;
    default:
        console.log('none');
}

14 循环结构 - while

//初始化循环条件
while(循环条件)
{
	表达式;
	//改变循环条件
}

15 循环结构 - do while

先运行再判断

do{
表达式;
}while();

17 循环结构 - for

//初始化循环变量
for(循环变量;判断条件;改变循环变量)
{
	表达式;
}

18 函数

18.1 函数定义

function 函数名(形参1,形参2···){
	函数内容;
	return 变量;
}

18.2 函数调用

语法: 变量 = 函数名(实参1,实参2···)

18.3 递归函数

调用 了自己的函数,递归意味传递参数回归数据的过程。

19 作用域

  • 范围全局作用域私有作用域,一个页面就是一个全局作用域,只有函数生成私有作用域

    // 全局作用域
    function a(){
    // 私有作用域a
        function b(){
        // 私有作用域b
        }
    }
    function c(){
        // 私有作用域c
    }
    

这里面,所有作用域都有全局作用域这个父级,而且 a 是 b 的父级

  • 使用:定义时,变量的作用域即为所处的作用域;
    访问时,作用域没有需要的变量就回去父级查找,若到全局都没有,报错;
    赋值时,自己有就给自己的赋值,自己没有就给父级赋值,若全局都没有,报错

20 对象数据类型 object

20.1 创建对象

var obj = { 键:值,健:值 },对象就是多个键值对的集合

20.2 增

var obj = {};
obj.= 值; //方法1
obj ["键" ] = 值; //方法2

20.3 删 delete

var obj = {};
delete obj.; //方法1
delete obj ["键"]; //方法2

20.4 改

  • 同增,对象内数据不能相同

    obj.= 修改值; //方法1
    obj ["键"] = 修改值; //方法2
    
  • 扩展:可以用Object.defineproperty( 对象, 属性, { 一些特性:特性值 } ),writeable:是否能被重写,value 为属性的属性值,enumerable:是否能被枚举,configurable:是否能被删除。

    var a = {
        id: 'jack',
        age: 18
    }
    Object.defineProperty(a,'id',{value: 'Rose', writable: false});
    console.log(a);  // a = 'Rose
    a.id = 'HHH';
    console.log(a);  // a = 'Rpse
    

20.5 查

a = obj.; //方法1
a = obj ["键"]; //方法2
a = ("key" in obj) // false
obj.hasOwnProperty("key")
JSON.stringify(obj) === '{}' ? '空' : '非空'

21 数组数据类型 array

  • 创建 var a = [ ];
  • 可以存任何数据类型,下标从 0 开始
  • 数组.lenght , 获取长度,长度是可以直接修改的;若修改了数组长度,则会相应的改变数组。

js 实现冒泡排序

var list = [3,1,6,5,8,9,7,2,4,10];
for(var i = 0; i<list.length-1;i++){
    for(var j = 0;j<list.length-1-i;j++){
        if(list[j]>list[j+1]){
            var temp = list[j];
            list[j] = list[j+1];
            list[j+1]=temp;
        }
    }
}
console.log(list);

22 数组常用方法

  1. push()方法,在数组最后追加数据,返回执行后的数组
  2. pop()方法,删除数组的最后一项,返回被删除的数据
  3. unshift()方法,在数组最前面添加数据
  4. shift()方法,删除数组最前面的数据,返回被删数据
  5. reverse()方法,反转数组,返回处理后的数组
  6. splice(开始索引,数量,要插入的数据)方法,删除从索引开始的那么多数量个数据,然后在被删除的地方插入要插入的数,不写代表不插入数据,以数组的形式返回被删除的数据
  7. sort(函数)方法,数组排序,返回排序后的数组,无传参时默认按照位从小到大排序,其他排序方法需要自己写函数来传递
  8. join(连接符)方法,将数组用连接符连接成一个字符串,并返回这个字符串
  9. concat(数组)方法,拼接两个数组
  10. slice(开始索引,结束索引) 方法,截取开始到结束的部分包前不包后),返回截取到的这个数组,不改变原始数组,只有一个参数时,表示截取至数组尾
  11. indexof(数据)方法,返回数据在数组中第一次出现的位置,没有则返回 - 1
  12. forEach(函数)方法,遍历数组,无返回值,对数组中每个数据执行传递的函数, 传递的函数最多可接受三个参数,item(数据),index(索引),arr(原始整个数组),forEach 没有返回,不可以改变数组内容
  13. map(函数)方法,按照函数方法返回映射后的数组map 可以有返回值,可以改变数组内容,以 return 返回
  14. filter(函数)方法,按照传递的函数方法过滤数组,返回过滤后的数组,以 return 返回
  15. every(函数)方法,按照函数判断数组是否每一项都满足条件,返回值是布尔
  16. some(函数)方法,判断数组是否有某一项满足函数条件,返回值是布尔
  17. reduce(回调函数, 初始值)回调函数累加调用
  18. flat([depth])返回一个可通过深拷贝得到的数组
var a = [1,2,3];
var b;
b = a.push("aaa"); // a = [1,2,3,"aaa"]
b = a.pop();       //a = [1,2,3]
b = a.unshift("aaa");  //a = ["aaa",1,2,3]
b = a.shift();        // a = [1,2,3]
b = a.reverse();  // a = [3,2,1]
b = a.splice();  //a = [1,2,3]
b = a.splice(1,1)//a = [2,3] 返回[1]
b = a.splice(1,1,2) //a = [2,2,3] 返回【1】
b = a.join("-");  // a = "1-2-3"
b = a.concat(a);  // a = [1,2,3,1,2,3]
b = a.slice(0,2); // a = [1,2]
b = a.indexof(3);  // a = 2
b = a.filter( function (item,index,arr){ return item > 2; }); // a = [3]
b = a.every( function (item,index,arr){ return item > 2; }); // a = false
b = a.some( function (item,index,arr){ return item > 2; }); // a = true
// sort
var a = [1,22,11,2];
var b;
b = a.sort(); // b = [1,11,2,22];
b = a.sort( function(a, b) { return a-b; } ); //a-b,从小到大排序 b = [1,2,11,22]
b = a.sort( function(a, b) { return b-a; } ); //b-a,从大到小排序 b = [22,11,2,1]
// forEach
a.forEach( function( item, index, arr) {
    console.log(item) 
    console.log(index)
    console.log(arr)
})
// map
a = a.map( function( item, index, arr) {
    return item*10;
})
console.log(a);

23 字符串常用方法

字符串也是按照索引由 0 开始的

  1. charAt(索引),返回索引位置的字符
  2. toLowerCase(),返回全部转成小写的字符串
  3. toUpperCase(),返回全部转成大写的字符串
  4. replace(被换内容,替换内容),字符串内第一个被换内容片段用替换内容替换,返回新的字符串,注意只替换一个片段
  5. trim()去除首尾空格,返回新串
  6. splict(分隔符)切割字符串,按照分隔符把字符串切割为一个数组,这里的分隔符是字符串中存在的,切割后的内容不包含分隔符,最后返回这个数组
  7. substr(开始索引,截取个数),返回截取到字符串
  8. substring(开始索引,结束索引),返回截取到字符串包前不包后
  9. slice(开始索引,结束索引),返回截取到字符串包前不包后
  10. 字符串没有直接的取反函数,可以用数组的 reverse,先把字符串切割,再反转,再拼接
var a = "abcabcddd";
a = a.replace("abc","def"); //a = "defabcddd"
var a = "2022-03-30";
a = a.splict("-");  // a = ["2022","03","30"]

深拷贝

  1. 使用递归的方式实现数组、对象的深拷贝;
  2. 通过 js 的内置对象 JSON 来进行数组对象的深拷贝, 无法实现对对象中方法的深拷贝
  3. 通过 jQuery 的 extend 方法实现深拷贝。
//使用递归的方式实现数组、对象的深拷贝
function deepClone1(obj,newObj) {
	//判断拷贝的要进行深拷贝的是数组还是对象,是数组的话进行数组拷贝,对象的话进行对象拷贝
	for(var k in obj){
		var item = obj[k];
		// 数组的判断要放在对象之前,因为对象属于数组
		if(item instanceof Array){
			newObj[k] = [];
			deepClone1(item, newObj[k])
		}
		else if(item instanceOf Object){
			newObj[k] = {};
			deepClone1(item, newObj[k])
		}
		else
			newObj[k] = item;
	}
}
//通过js的内置对象JSON来进行数组对象的深拷贝
function deepClone2(obj) {
  var _obj = JSON.stringify(obj),
    objClone = JSON.parse(_obj);
  return objClone;
}
//通过jQuery的extend方法实现深拷贝
    var array = [1,2,3,4];
    var newArray = $.extend(true,[],array);

24 数字常用方法

24.1 常用方法

用于计算的一些数学方法

  1. Math.random(),返回 0~1 之间的随机小数
  2. Math.round(数字)四舍五入取整数
  3. Math.ceil(数字)向上取整
  4. Math.floor(数字)向下取整
  5. Math.pow(底数,指数)取幂,底数的指数次方运算结果
  6. Math.sqrt(数字)算数平方根,只保留正数部分
  7. Math.abs(数字)返回绝对值
  8. Math.max(数字1,数字2,数字3···),返回最大值
  9. Math.min(数字1,数字2,数字3···),返回最小值
  10. Math.PI ,不是方法,是属性近似Π值

24.2 应用 随机整数

想要获取 x ~ y 之间的随机整数,先获取 0 ~ (y-x)之间的随机整数,然后给这个数字加上 x 就可以,
那么相对随机的获取 0 ~ x 之间的随机整数呢,random()可以获得 0 ~ 1 之间的随机小数,我们把它乘以 x,就可以得到 0~x 之间的随机数,然后取整就可以,重点在于取整,四舍五入会导致 0 和 x 的取值概率小于其他数字,这里应该选择 random()乘以 x+1,然后向下取整即可.

function randomNum(x, y) {
  	var a = Math.floor(Math.random()*(y-x+1))+x;
	return a;
}
console.log(randomNum(10,12));

25 时间常用方法

时间本身也是 js 中的一个数据类型 Date,var time = new Date(),可以获得电脑当前时间,如果传递了参数,就可以获得指定时间对象,参数有顺序,var time = new Date( 年,月,日,时,分,秒)注意月份是从 0 开始的,11 就表示 12 月

25.1 获取方法

返回的都是数字
2022 年 4 月 10 日,16:50:30,周日

  1. 时间对象.getFullYear()份,2022
  2. 时间对象.getMonth()份,3
  3. 时间对象.getDate()日期,10
  4. 时间对象.getHours()小时,16
  5. 时间对象.getMinutes()分钟,50
  6. 时间对象.getSeconds(),30
  7. 时间对象.getDay()周几,7
  8. 时间对象.getTime(),时间戳,相对于计算机元年相隔的毫秒数(计算机元年是 1970 年 1 月 1 日 0:0:0)

25.2 设置方法

没有设置星期的方法,会自动匹配

  1. 时间对象.setFullYear(数字)
  2. 时间对象.setMonth(数字)
  3. 时间对象.setDate(数字)
  4. 时间对象.setHours(数字)
  5. 时间对象.setMinutes(数字)
  6. 时间对象.setSeconds(数字)
  7. 时间对象.setTime(数字)

25.3 获取两个时间结点之间的时间差

function getDiff(time1, time2){
        var ms1 = time1.getTime(); //为了计算,先全部转换成时间戳
        var ms2 = time2.getTime();
        var sub = Math.ceil((ms2-ms1)/1000);
        var day = Math.floor(sub/(60*60*24));
        var hours = Math.floor(sub%(60*60*24)/(60*60));
        var seconds = sub%60;

        return {day:day,hours:hours,seconds:seconds};
    }

26 BOM 基本操作

26.1 获取浏览器窗口尺寸

  1. 宽度: window.innerWidth
  2. 高度: window.innerHeight
    返回 px 数字值

26.2 浏览器弹出层

  1. 提示框:window. alert(内容),只有确定按钮,无返回
  2. 询问框:window. confirm(内容),有确定和取消按钮,返回 true 或者 fasle
  3. 输入框:window. prompt(内容),有输入框和确定取消按钮,点击确定,返回输入框内容,点击取消返回 null

26.3 开启和关闭标签页

  1. 开启:window. open(“地址”)
  2. 关闭:window. close()

26.4 浏览器的历史操作

  1. 回退:window. history.back()
  2. 前进:window. history.forward()

26.5 浏览器的常见事件

事件发生后才执行后面的函数

  1. 资源加载完毕:window. onload = function(){ }
  2. 页面尺寸改变:window. onresize = function(){ }
  3. 滚动条位置改变:window. onscroll = function(){ }

26.7 浏览器卷去的尺寸

当页面超出窗口宽高是,超出窗口的 px 数值,兼容的写法是用 || 来获得需要的内容

  1. 高度
    document. documentElement.scrollTop(),有 doctype 标签时使用
    document. body.scrollTop,没有 doctype 标签时使用
  2. 宽度
    document. documentElement.scrollLeft(),有 doctype 标签时使用
    document. body.scrollLeft,没有 doctype 标签时使用

26.8 浏览器滚动到

让浏览器定位,通过设置浏览器卷去的宽度和高度来实现

  1. 瞬间定位,window. scrollTo(卷去的宽度,卷去的高度)
  2. 可以设置定位方式,如:behavior: 'smooth'平滑滚动
window. scrollTo({
	left:xx,
	top:yy,
	behavior:'smooth'
})

27 定时器

27.1 定时器的开启

  1. 间隔定时器,每间隔一段时间修改一次,
    setInterval(函数,时间),时间单位是毫秒
  2. 延时定时器,只执行一次
    setTimeout(函数,时间),时间单位是毫秒
setInterval(function(){
        console.log("执行了一次");
    },1000)

27.2 定时器的返回值

定时器的返回值表示这是页面上的第几个定时器,不区分定时器种类var time1 = setInterval()

27.3 定时器的关闭

  1. clearInterval(要关闭的定时器返回值)
  2. clearTimeout(要关闭的定时器返回值)
    注意:定时器的关闭是不区分种类的,可以随便用。
<body>
    <button id = 'closeTimer'>关闭</button>
	<script>
		var timer1 = setInterval(function(){ console.log('间隔定时器')},1000);
		var timer2 = setTimeout(function(){ console.log('延时定时器')},3000);
		closeTimer.onclick = function(){
		    clearInterval(timer1);
		    clearInterval(timer2);
		}
	</script>
</body>

28 DOM 的基本操作

DOM - Document Object Model:一整套操作文档流相关内容的属性和方法,可以利用这些方法操作元素修改样式、修改属性、改变位置、添加事件等等。

28.1 获取元素的方式

  1. 根据 id 名称获取:document. getElementById(“id名”),获取文档流中 id 对应的一个元素,没有相应的元素则返回 null
  2. 根据类名获取元素:document. getElementsByClassNmae(“类名”),获取文档流中类名对应的所有元素,返回伪数组,没有对应的元素则返回空的伪数组
  3. 根据标签名获取元素,document. getElementsByTagName("标签名“),获取文档流中所有标签名对应的元素,返回伪数组
  4. 根据选择器获取一个元素,document. querySelector(”选择器“),获取文档流中满足选择器的第一个元素,返回元素,没有则返回 null
  5. 根据选择器选择一组元素,document. querySelectorAll(”选择器“),获取文档流中满足选择器的所有元素,返回伪数组,没有则返回空的伪数组
// 选择器获取
var eles = document.querySelectorAll('div .box');

28.2 操作元素内容

  1. 文本内容:元素. innerText,纯文本
  2. 超文本内容:元素. innerHTML,带有 html 结构的内容(含有标签),会自动改变内部结构
<body>
    <button>点我</button>
    <div>
        <p>这是p标签</p>
    </div>
<script>
var btn = document.querySelector('button');
var div = document.querySelector('div');
var p = document.querySelector('p')

btn.onclick = function(){
    p.innerText = '我不是p标签';
    setTimeout(function(){
        div.innerHTML = '<span>这是一个span标签<span>';
    },1000)
}
</script>
</body>

28.3 操作元素的原生属性

  1. 获取:元素. 属性名
  2. 设置:元素. 属性名 = ‘ 属性值 ’
    原生属性不能删除,类名不能这样修改。
div.id = 'content';
input.type = 'password';

28.4 操作元素自定义属性

  1. 获取:元素. getAttribute('属性名')
  2. 设置:元素. setAttribute('属性名',属性值)
  3. 删除:元素. removeAttribute('属性名')
    自定义属性是我们用来存一些数据或者传递数据用的,可以删除。

28.5 操作元素类名

  1. 获取:元素. className
  2. 设置:元素. className = '新类名'

28.6 操作元素行内样式

带有 - 的样式名,在书写时要去掉 - 而改写为驼峰命名法,比如 background-color应该写为backgroundColor

  1. 获取:元素. style. 样式名
  2. 设置:元素. style. 样式名 = ' 样式值 ’

28.7 获取非行内样式

window. getComputedStyle(元素). 样式名
这个方法可以获得非行内样式,也可以获得行内样式。
前端 js 只能设置行内样式,没有设置非行内样式的方法。

28.8 js 回到顶部案例

  • 确认需求:当滚动条超过临界点时,顶部通栏和回到顶部按钮显示,否则隐藏;点击回到顶部按钮,滚动条回到顶部。
  • 布局结构:需要一个顶部通栏标签和一个回到顶部标签;让页面大于可视窗口,出现滚动条;设置顶部通栏和回到顶部样式,默认都是隐藏的;
  • 给浏览器绑定滚动事件,给按钮绑定点击事件

回到顶部案例

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="utf-8">
    <meta >
    <title>web001</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        ul,ol,li{
            list-style: none;
        }
        html,body{
            height:100%;
        }
        body{
            height: 3000px;
        }
        .menu{
            background-color: pink;
            height: 80px;
            width: 100%;
            color: white;
            line-height: 80px;
            text-align: center;
            font-size: 24px;

            position: fixed;
            top: -80px;
        }
        .goTop{
            background-color: pink;
            width: 62px;
            height: 62px;
            border: 6px solid palevioletred;
            border-radius: 15px;
            box-shadow: 3px 3px 2px gray; 
            color: white;
            font-size: 20px;
            line-height: 20px;
            padding: 5px;
            box-sizing: border-box;
            /* 位置 */
            position: fixed;
            right: 50px;
            bottom: 50px;
            /* 鼠标样式 */
            cursor:pointer; 
            /* 显示 */
            display: none;
        }
    </style>
</head>
<body>
    <header class="menu">菜单</header>
    <div class="goTop">回到顶部</div>
    <script>
        var header = document.querySelector('.menu');
        var goTop = document.querySelector('.goTop');
        // 给窗口绑定滚动事件
        window.onscroll = function(){
            if(document.documentElement.scrollTop>300){
                header.style.top = '0px';
                goTop.style.display = 'block';
            }
            else{
                header.style.top = '-80px';
                goTop.style.display = 'none';
            }
        }
        // 给按钮绑定事件,浏览器滚动到顶部
        goTop.onclick = function(){
            window.scroll({
            top:0,
            behavior:"smooth"
        })
        } 
    </script>
</body>
</html>

28.9 js 选项卡案例


<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="utf-8">
    <title>web001</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        body{
            height:3000px;
        }
        ul,ol,li{
            list-style: none;
        }
        .box{
            width: 600px;
            height: 400px;
            border: 3px solid pink;
            margin: 50px auto;
            flex-direction: column;
        }
        .box>ul{
            height:100px;
            display: flex;
        }
        .box>ul>li{
            flex:1;
            color:#fff;
            background-color: skyblue;
            font-size: 30px;
            display: flex;
            justify-content: center;
            align-items: center;
            cursor: pointer;
        }
        .box>ul>li.active{
            background-color: orange;
        }
        .box>ol{
            flex:1;
           position: relative;
        }
        .box>ol>li{
            height: 300px;
            width: 100%;
            background-color: purple;
            justify-content: center;
            align-items: center;
            color: #fff;
            font-size: 100px;

            position: absolute;
            left:0px;
            top:0px;

            display: none;
        }
        .box>ol>li.active{
            display: flex;
        }
    </style>
</head>
<body>

<div class="box">
    <ul>
        <li class="active">1</li>
        <li>2</li>
        <li>3</li>
    </ul>
    <ol>
        <li class="active">1</li>
        <li>2</li>
        <li>3</li>
    </ol>
</div>

<!-- js语言的执行特点,导致代码一定要放在最后 -->
<script>
    // 1.获取元素
    var btns = document.querySelectorAll("ul > li");
    var tabs = document.querySelectorAll("ol > li");
    // 2.利用循环给所有按钮添加点击事件
    btns.forEach(function(item,index){
    	// 3.发生点击事件,先将所有盒子类名取消,也就取消了所有样式
        item.onclick = function(){
            btns.forEach(function(t,i){
                t.className = '';
                tabs[i].className = '';
            })
    	// 4.给被点击的按钮和盒子显示
        item.className = "active";
        tabs[index].className = "active";
        }
    })
</script>
</body>
</html>

29 DOM 基本操作 续

节点操作:就是通过 js 进行一系列节点操作,不需要 html 的辅助。

29.1 创建节点

  • 语法:document. createElement(‘标签名称’)
  • 作用:创建一个指定标签元素
  • 返回值:一个创建好的元素结点
var div1 = document. createElement('div');
 div1.innerText="我是js创建出来的div1";

29.2 插入节点

  • 语法 1:父节点. appendChild(子节点)

  • 作用:把子节点插入到父节点内部,并放到最后的位置

  • 语法 2:父节点. insertBefore(要插入的结点,哪一个子节点之前)

  • 作用:把创建的子节点放在父节点内部,并且可以指定放在哪个子节点之前

<body>
    <div>
        <span>这是div本来就有的span</span>
    </div>
    <script>
        var div = document.querySelector('div');
        var span = document.querySelector('span');
        var div1 = document. createElement('div');
        var div2 = document. createElement('div');
        div1.innerText="我是js创建出来的放在后面的div1";
        div2.innerText="我是js创建出来的放在前面的div2";
        div.appendChild(div1);  
        div.insertBefore(div2,span);
    </script>
</body>

29.3 删除节点

  • 语法 1:父节点. removeChild(子节点)

  • 作用从父节点内删除一个子节点

  • 语法 2:节点. remove()

  • 作用:删除自己

29.4 替换节点

  • 语法:父节点. replaceChild(换上节点,换下节点)
  • 作用:在父节点内,使用换上节点替换换下节点

29.5 克隆节点

  • 语法:节点. cloneNode(是否克隆后代节点 true / flase)
  • 作用:把该结点复制一份一模一样的内容
  • 返回值:克隆后得到的元素节点

29.6 获取元素尺寸

元素尺寸:元素的边框 border + 内边距 padding + 内容

  • 语法 1:高 元素. offsetHeight
    元素. offsetWidth

  • 作用:获取 元素 内容 + padding+border 的区域尺寸

  • 语法 2:高 元素. clienthHeight
    元素. clientWidth

  • 作用:获取元素 内容 + padding 的区域尺寸,不算边框

29.7 案例 - 动态渲染数据

案例:将后端传过来的数据渲染成一个表格

var user = [
        	{ id:1,name:'用户1',age:18},
       	 	{ id:1,name:'用户2',age:20},
        	{ id:3,name:'用户3',age:22}
    	   ]
  1. 先创立一个 tr 标签
  2. 循环遍历数据,创建多少个 td,把数据添加到 td 标签,把 td 插入到 tr 内
  3. 把 tr 插入到父盒子内部
<body>
    <table border="1" cellspacing="0">
        <thead>
            <tr>
                <th>ID</th>
                <th>姓名</th>
                <th>性别</th>
            </tr>
            <tbody>

            </tbody>
        </thead>
    </table>
    <script>
    var user = [
        { id:1, name:'用户1', age:18 },
        { id:2, name:'用户2', age:20 },
        { id:3, name:'用户3', age:22 }
    ];
    var tbody = document.querySelector('tbody');
    user.forEach(function(item){
        console.log(item);
        var tr = document.createElement('tr');
        for(var key in item){
            var td = document.createElement('td');
            td.innerText = item[key];
            tr.appendChild(td);
        }
        tbody.appendChild(tr);
    });
    </script>
</body>

30 事件

前端:通过代码的方式和页面中的某些内容做好一个约定
用户:触发指定行为的时候就会执行指定代码

30.1 事件绑定

事件绑定三要素

  1. 事件源:和谁做好约定
  2. 事件类型:约定一个声明行为
  3. 事件处理函数:当用户除法该行为时,执行什么代码
  • 传统方式注册事件源. on事件类型 = 事件处理函数
    特点:注册事件的唯一性,这种方式同一个元素的同一个事件只能有一个处理函数,后面的会覆盖前面的
  • 事件监听监听注册事件源.addEventListenr(事件类型,事件处理函数)
    特点:IE9 之前的 IE 不支持这种方法,可以用attachEvent()代替,同一个元素同一个事件可以以注册多个监听器,按注册顺序依次执行。
  • attachEvent()只有 IE9 以前的版本支持。
<script>
    var div = document.querySelector('div');
    div.onclick = function(){
        alert("你好");
    }
    div.addEventListener('click',function(){
        console.log('点了我一下');
    })
</script>

30.2 常用事件类型

常用的

汇总

原文:http://tools.jb51.net/table/javascript_event






30.3 事件对象

事件对象

事件对象:当触发事件的时候,一个描述该事件信息的对象数据类型
理解:每次触发事件的时候,浏览器都会用一个对象来保存这次触发事件的相关信息,不用事件信息内容组成是不同的。
在绑定事件函数的时候,在函数内传入一个形参,浏览器会自动把数据保存到这个参数然后返回
注意:每次触发事件都会生成一个新的对象,即使触发函数相同

<script>
    var div = document.querySelector('div');
    div.onclick = function(e){
        consloe.log(e);
    }
</script>

事件对象内的常用信息

1. 鼠标事件

坐标信息

  • offsetXoffsetY
    相对于触发元素的内部定位
  • clientXclientY
    相对于浏览器可视窗口的目标定位
  • pageXpageY
    相对于页面文档流的位置
2. 键盘事件

键盘编码 事件对象. keycode(现已弃用,用code)

document.onkeydown = function(e){
    console.log('code: '+e.code);
    console.log('keycode: '+e.keyCode)
}

30.4 案例 - 鼠标跟随

鼠标跟随案例

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="utf-8">
    <title>web001</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        ul,ol,li{
            list-style: none;
        }
        img{
            width: 50px;
            height: 50px;
            position: fixed;
            left:0;
            top:0;
        }
    </style>
</head>
<body>
    <img src="春节-花.png" alt="">

    <script>
        var img = document.querySelector('img');
        //1.给document绑定一个鼠标移动事件
        document.onmousemove = function(e){
            //2.拿到鼠标相对于窗口的定位
            var x = e.clientX;
            var y = e.clientY;
            //3. 把拿到的坐标给小花定位
            img.style.left = x - 20+'px';
            img.style.top = y - 20+'px';
        }
    </script>
</body>
</html>

30.5 事件传播

事件传播就是浏览器响应事件的机制
如图,当点击行为发生在 inner 上时,首先是 window 感知点击行为,然后再一层层向内传播信息直到 inner 收到信息才知道自己被点击了;
然后 inner 会向外一层层传递信息,告知有人点击了它,一直到 window 结束。

  • 事件目标:这里的 inner 就是本次事件的目标
  • 捕获:从 window 到目标
  • 冒泡:从目标到 window

    事件响应机制
    浏览器窗口最先知道事件的发生
    捕获阶段:从 window 按子级到目标传递信息
    目标阶段:准确触发事件的元素接收到行为信息
    冒泡阶段:从目标按父级到 window 传递行为信息

由此可见,若父元素都绑定了发生在子元素上的行为触发事件,则在子元素被触发的情况下,父元素也会触发事件,因为子元素的行为信息是一层层向外传递的。

30.6 阻止事件传播

有时候,为了让子元素事件触发不影响到父元素,必须组织事件传播
语法:事件对象. stopPropagation()

var inner = document.querySelector('.inner');
inner.onclick = function(e){
	e.stopPropagation();
}

30.7 事件委托

利用事件冒泡机制,把自己的事件委托给结构父级中的某一层
事件对象. target 可以获得点击的对象,事件对象. target. tagName就是该对象的名称。
那么发生触发事件后,我们可以先判断该对象是不是满足某些条件,若满足,委托的父元素绑定该事件。
e.target.className 为类名,

<body>
   <ul>
       <li>1</li>
       <li>2</li>
       <li>3</li>
   </ul>
    <script>
        var ul = document.querySelector('ul');
        ul.onclick = function(e){
            if(e.target.tagName === 'LI'){
                console.log("点击了li");
            }
        }
    </script>
</body>

30.8 轮播图案例

轮播图案例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <!-- <meta http-equiv="X-UA-Compatible" content="IE=edge"> -->
    <!-- <meta > -->
    <title>轮播图案例</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        ul,ol,li{
            list-style: none;
        }
        html,body{
            height:100%;
        }
        img{
            width: 100%;
            height: 100%;
        }
        .banner{
            width: 450px;
            height: 302px;
            /* 图片要全部定位在盒子正中间 */
            position: relative;
            margin: 50px auto;
        }
        
        .banner > ul{
            width: 100%;
            height: 100%;

            position: relative;
        }
        .banner > ul > li{
            width: 100%;
            height: 100%;

            position: absolute;
            left: 0;
            top: 0;

            /* 只显示一张,所以先全部设置为透明,需要的li单独设置 */
            opacity: 0;

            transition: opacity 0.5s linear;
        }
        .banner > ul > li.active{
            opacity: 1;
        }

        .banner > ol{
            width: 120px;
            height: 20px;
            position: absolute;
            left: 10px;
            bottom: 10px;
            padding: 0 5px;
            background-color: rgba(0,0,0,0.3);

            display: flex;
            justify-content: space-around;
            align-items: center;
            border-radius: 10px;
        }

        .banner > ol > li{
            width: 6px;
            height: 6px;
            background-color: #fff;
            border-radius: 50%;
            cursor: pointer;
        }
        .banner > ol > li.active{
            background-color: orange;
        }

        .banner > div{
            width: 20px;
            height: 25px;
            position: absolute;
            top: 50%;
            transform: translateY(-50%);
            background-color: rgba(0,0,0,0.3);

            display: flex;
            justify-content: center;
            align-items: center;
            font-size: 20px;
            color: #fff;
            cursor: pointer;
        }
        .banner .right{
            position: absolute;
            right: 0px;
        }
    </style>
</head>
<body>
    <div class="banner">
        <!-- 图片区域 -->
        <ul class="imgBox">
            <li class="active"><img src="../img/轮播图1.jpg"></li>
            <li><img src="../img/轮播图2.jpg"></li>
            <li><img src="../img/轮播图3.jpg"></li>
            <li><img src="../img/轮播图4.jpg"></li>
            <li><img src="../img/轮播图5.jpg"></li>
            <li><img src="../img/轮播图6.jpg"></li>
            <li><img src="../img/轮播图7.jpg"></li>
            <li><img src="../img/轮播图8.jpg"></li>
            <li><img src="../img/轮播图9.jpg"></li>
            <li><img src="../img/轮播图10.jpg"></li>
        </ul>

        <!-- 焦点区域 -->
        <ol>
            <li class="active" data-></li>
            <li data-></li>
            <li data-></li>
            <li data-></li>
            <li data-></li>
            <li data-></li>
            <li data-></li>
            <li data-></li>
            <li data-></li>
            <li data-></li>
        </ol>

        <!-- 左右切换按钮 -->
        <div class="left"><</div>
        <div class="right">></div>
    </div>

<script>
    // 先获取我们要操作的图片li和焦点li
    var imgs = document.querySelectorAll('ul > li');
    var points = document.querySelectorAll('ol > li');
    // 所有按钮都在banner内,点击按钮都会触发banner点击事件,可以通过banner点击事件判断点击的是什么
    var banner = document.querySelector('.banner')
    // 因为要让图片按顺序显示,准备一个变量存当前展示的是第几张
    var index = 0;
    // 切换图片的函数,通过参数来决定切换上一张、下一张、还是 某一张
    // 参数的值可以自己规定,这里规定上一张true、下一张false、某一张 数字
    function changeOne(type){
        // 当前图片隐藏,这里的css与active类名绑定
        imgs[index].className = '';
        points[index].className = '';
        // 先修改index值为点击后要展示的图片索引
        if(type === true)
            index++;
        else if(type === false)
            index--;
        else
            index = type;
        // index超出边界的情况(循环轮播)
        if(index>imgs.length-1)
            index = 0;
        else if(index<0)
            index = imgs.length-1;
        // 给当前index添加类名
        imgs[index].className = 'active';
        points[index].className = 'active';
    }
    // 给相应按钮绑定点击事件,传递不同参数
    banner.onclick = function(e){
        // 点击左按钮,切换上一张
        if(e.target.className === 'left')
            changeOne(false);
        // 点击右按钮,切换下一张
        else if(e.target.className === 'right')
            changeOne(true);
        // 点击焦点,切换到对应索引
        else if(e.target.dataset.name === 'point')
            changeOne(e.target.dataset.i - 0);
    }
    //  最后写一个自动播放函数,运用定时器即可
    setInterval(function(){
        changeOne(true)
    },3000)
</script>
</body>
</html>

30.9 js 事件执行机制

同步任务

在主线程上执行,形成一个执行栈

异步任务

js 的异步任务通过回调实现
异步任务一般有以下三类:

  1. 普通事件:如 click、resize 等
  2. 资源加载:如 load、error 等
  3. 定时器:包括 setInterval、setTimeout 等

执行机制

先执行完同步任务,然后执行一个异步任务,每执行完一个异步任务都要回到同步任务队列,只有同步任务队列为空才会执行异步任务。
执行异步任务时同样要先执行微任务再执行宏任务

  • 宏任务:script(全局任务), setTimeout, setInterval, setImmediate, I/O, UI rendering.
  • 微任务:process.nextTick (node.js 中进程相关的对象), Promise , Object.observer, MutationObserver

31 面向对象

31.0 面向对象

面向过程:一种关注过程的开发方式,在开发过程中关注每一个细节、步骤、顺序
面向对象:一种面向对象的开发方式,开发过程中,优先考虑有没有一个对象帮助解决问题,
面向对象的核心:高内聚低耦合(就是对面向过程的高度封装)

  • 构造函数
  • 可以批量生产对象的函数
  • 可以传递参数,给不同对象添加不同内容

31.1 创建对象的方式

  1. 字面量方式创建对象
    var obj = {···},可以后期动态添加
var obj = {
	name:"Jack",
	age:18,
	sayHi: function(){
		console.log("hello!")
	}
};
  1. 内置构造函数创建对象
var obj = new Object();
obj.name = 'Jack';
obj.age = 18;
obj.sayHi = function(){ console.log("hello!") };
  1. 类函数创建对象,先制造一个类,然后使用类创造对象
function createObj(name,age){
	var obj = {};
	obj.name = name;
	obj.age = age;
	obj.sayHi = function(){console.log("hello!") };
	return obj;
}
var obj = createObj('Jack',18);
  1. 自定义构造函数对象,使用的时候函数要和 new 连用才能创造对象,否则没有意义
    示例中,每次和 new 连用之后,自定义函数中的 this 就指向了变量 obj1 和 obj2
function createObj(name,age){
	this.name = name;
	this.age = age;
	this.sayHi = function(){console.log("hello!") };
}
var obj1 = new createObj('Jack',18);
var obj2 = new createObj('Rose',20);

31.2 构造函数的使用

  1. 构造函数和普通函数没有区别,只是要和 new 关键字连用
  2. 为了便于区分,一般构造函数函数名首字母大写
  3. 必须和 new 连用才有创建对象的能力
  4. 调用构造函数时,如果不需要传递参数,可以不写最后的小括号(一般还是写上)
  5. 实例成员静态成员,实例成员就是 this 创建的,只能通过实例来访问,var s = new Star(), s.name静态成员就是构造函数本身的成员,只能通过构造函数来访问Star.sex = '男'
  6. 当函数名和 new 关键字连用时,this 指向当前实例,在函数体内写 this.xxx 就行
  7. 函数内不要随便写 return
    如果 return 了一个基本数据类型,return 写了也白写,拿不到返回值;
    如果 return 了一个复杂数据类型,构造函数白写,对象为返回

31.3 构造函数的不合理

按照之前的写法,构建一个有对象有方法的函数,那么只要创建一次函数对象,就会为这个对象添加一个方法创建一个函数,就有一个函数在占用空间,创建的对象多了,这个开销是很大的。

31.4 原型 prototype、__ proto __

  • prototype 是每一个函数天生自带的一个属性也是一个对象,我们可以用对象操作的语法向里面添加一些内容,扩展对象的内容。
  • ** _ _ proto _ _ ** 是每个对象自带的属性,指向了所属构造函数的 prototype
    对于构造函数的每一个实例对象,在访问它的某一个成员时,如果找不到,就去其_ _ proto _ _中查找,也即是构造函数的原型中找
    通过这个原型,我们可以把构造函数中的方法放到它的原型中,当实例化对象需要使用这个函数时,才到原型中去找出来然后创建函数,这样就解决了构造函数不合理的问题。
function Person(name,age){
	this.name = name;
	this.age = age;
}
// 注意函数原型不要写在构造函数内哦
Person.prototype.sayHi = function(){console.log("hello!") };

31.5 简单版面向对象选项卡案例

js 选项卡案例

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="utf-8">
    <meta >
    <title>简单版选项卡案例</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        ul,ol,li{
            list-style: none;
        }
        html,body{
            height:100%;
        }
        .tab{
            width: 400px;
            height: 300px;
            border: 5px solid gray;
            margin: 50px auto;
            display: flex;
            flex-direction: column;
        }
        .tab > ul{
            height:60px;
            display: flex;
        }
        .tab > ul >li{
            flex:1;
            display: flex;
            background-color: pink;
            font-size: 30px;
            color: white;
            justify-content: center;
            align-items: center;
            cursor: pointer;
        }
        .tab > ul > li.active{
            background-color: lightsalmon;
        }
        .tab ol{
            position: relative;
            flex:1;
        }
        .tab ol li{
            position: absolute;
            display: none;
            left: 0;
            top: 0;
            width: 100%;
            height: 100%;
            font-size: 100px;
            justify-content: center;
            align-items: center;
            color: white;
            background-color: blueviolet;
        }
        .tab > ol > li.active{
            display: flex;
        }
    </style>
</head>
<body>
    <div class="tab">
        <ul>
            <li class="active">1</li>
            <li>2</li>
            <li>3</li>
        </ul>
        <ol>
            <li class="active">1</li>
            <li>2</li>
            <li>3</li>
        </ol>
    </div>

<script>
// 1.抽象内容:一个能完成选项卡的对象应该有哪些属性和方法呢?
// 属性:需要操作的盒子,有可点击的按钮,可切换的卡页;方法:给每个按钮添加点击事件,实现切换选项卡

// 约定使用这个构造函数时必须传入最外侧div盒子的选择器
function Tabs(ele){
    this.ele = document.querySelector(ele);
    // 找到需要的属性
    this.btns = this.ele.querySelectorAll('ul>li');
    this.tabs = this.ele.querySelectorAll('ol>li');
}
// 方法写在原型上
Tabs.prototype.change = function(){
    _this = this;
    // 对每个按钮添加点击事件
    for(var i = 0; i < this.btns.length; i++){
        // 这里一定要先把每个按钮对应的i保存起来,
        // 因为一旦运行,只是绑定了点击函数,实际上发生点击时已经运行完,i的值被改变
        // 创建一个新的自定义属性index来保存
        this.btns[i].setAttribute('index',i);
        this.btns[i].onclick = function(){
            // 先清除所有按钮的类名,再给当前索引添加类名
            // 要注意这里的this已经不包含btns了,所以之前要先存好含有btns的this
            for(var j = 0; j< _this.btns.length; j++){
                _this.btns[j].className = '';
                _this.tabs[j].className = '';
            }
            this.className = 'active';
            var index = this.getAttribute('index') - 0;
            _this.tabs[index].className = 'active';
        }
    }
}
// 使用时只要拿选择器构造对象再调用函数就行
var t1 = new Tabs('.tab');
t1.change();
</script>
</body>
</html>

31.6 原型链

  • js 中,有一个 Object 内置构造函数和 Function 内置构造函数,所有对象都属于 Object 创造,所有函数都属 Function 创造;
  • 所以,原型是一个对象,那么它的_ _ proto _ 应该指向 Object 的原型,而构造函数的 _ proto _ _也该指向 Function 原型,
  • Object 是一个函数,它的_ _ proto _ 指向 Function 的原型,Function 也是一个函数,它的 _ proto _ _也指向 Function 的原型,
  • Object 的原型是一个对象,它的_ _ proto _ _按理说应该指向 Object 的原型,也就是自己,但 js 设置它为 null
  • Function 的原型是一个对象,它指向 Object 的原型。


原型链:就是 ** 用 _ _ proto _ _** 串联起来的对象链状结构,每一个对象数据类型都有自己的原型链,它一定是单链
使用:当访问对象某个成员时,如果自己没有,就会沿着原型链查找,直到链尾。

31.7 函数扩展

31.7.1 函数的调用方式

  1. 普通函数

    function fn(){	}
    fn();
    
  2. 对象的方法

    var o= {
    	fn() {	}
    }
    o.fn();
    
  3. 构造函数

    function Fn() {	}
    
  4. 绑定事件函数

    $('div').onclick = function() {	};
    
  5. 定时器函数

    setInterval( function(){ },1000);
    
  6. 立即执行函数
    立即执行函数不需要调用,会立即执行。

    ( function() { })();
    

31.7.2 一些改变 this 指向的方法

(1) call() 方法
  • 作用:改变函数的 this 指向,调用函数

  • 语法:函数.call( thisArg, arg1, arg2,...),第一个参数表示 this 指向,后面的为传参

  • 主要用于继承,在子函数内调用父构造函数,Father.call(this, a, b);

    function Fn(a, b){ 
    	console.log(this);
    	console.log(a+b);
    }
    var o = { name: 'Jack' }
    Fn.call(o, 1, 2); //o{...} 3
    
(2) apply() 方法
  • 作用:改变函数的 this 指向,调用函数

  • 语法:函数.apply( thisArg, [ arg1, arg2,... ] ),第一个参数表示 this 指向,参数以数组传进去

  • 主要应用:apply 求数组最大最小值,本来要遍历,现在可以Math.max.apply( Math, [1,2,3,4])

    function Fn(a, b){ 
    	console.log(this);
    	console.log(a+n);
    }	
    var o = { name: 'Jack' }
    Fn.call(o, [1, 2]); //o{...} 3
    
(3) bind() 方法
  • 作用:改变函数的 this 指向,但不会调用函数,而是返回原函数改变 this 之后产生的新函数

  • 语法:var a = 函数.bind( thisArg, arg1, arg2,... ),第一个参数表示 this 指向,后面是参数

  • 主要应用:如果某些函数不想立即调用,但是又想改变 this 指向,就用 bind;

    function fn(){ console.log(this);
    var o = { name: 'Jack' };
    var newFn = fn.bind(o);
    

31.8 继承

  1. 利用类继承,类的本质还是函数
  2. 借用父构造函数继承,注意这样在继承写在原型上的函数时,不要直接给子原型赋值为父原型,原型相当于指针,这样会同时修改父亲,应该让子原型等于父亲的对象,这样父亲的原型就在子的原型链上。

31.9 高阶函数

  • 定义:对其他函数进行操作的函数,它接受函数作为参数,或者将函数作为返回值输出

32 ES6 语法

2015 年版本
语法糖:一种便捷写法,当有两个方法都可以实现同一个功能时,更清晰方便的写法就是语法糖

33 ES6 - 定义变量

let:定义变量
const:定义常量

let、const 与 var 的区别:

  • var 会进行预解析,let/const 不会:定义之前就可以使用,只不过没有赋值,内容为 undefined;
  • var 可以声明两个重名的变量,let/const 不可以:var 可以在同一个作用域声明相同名称的变量,后面的相当于赋值;
  • var 没有块级作用域,let/const 有块级作用域:块级作用域指任何一个代码段的 {} 都会限制该变量的使用范围

let 与 const 的区别:

  • let 可以在定义的时候不赋值,const 定义的时候必须赋值
  • let 定义的变量后面可以修改值,const 不可以修改

34 ES6 - 箭头函数

34.1 定义

  • 箭头函数,是 ES6 的语法中对函数表达式的简写 ()=>{}
  • 没有函数名,通常是赋值给变量,用变量来调用函数,对于声明式函数不能使用
  • 在规则上又和以前的函数有些不一样:比如只有一个形参可以省略小括号只有一句代码可以省略大括号,箭头函数内没有 this 的绑定,this 只指向他被定义的位置的 this、没有 argument
// 语法示例
xxx.onclick = ()=>{};  // xxx.onclick = function() {}
var obj = { fn: () =>{} };  //var obj = { fn = function() {} }
xxx.forEach( ()=>{} );  // xxx.forEach( function(){} )
setTimeout( ()=>{}, );  // setTimeout( function(){},)
var fn = () =>{};  // var fn = function() {}

34.2 考点

var age = 100;
var obj = {
    age:20,
    say:()=>{
        console.log(this.age);
    }
}

obj.say();

这里会输出 100,因为 obj 并没有 this,箭头函数里的 this 就指向了 window。

35 ES6 - 数组

35.1 set 数据结构

  • 它类似于数组,但是成员的值都是唯一的,没有重复的值。

  • 可以利用 set 对数组直接去重

  • 常用方法:

    1. add(value):添加,返回 set
    2. delete(value):删除,返回是否成功删除的布尔值
    3. has(value):查找,返回是否有这个值的布尔值
    4. clear():清空 set,没有返回
    var s1 = new Set([1,2,3,3,4,4]);  //s1 =  [1,2,3,4]
    var s2 = new Set();
    s2.add(1).add(2); //s2 = [1,2]
    s2.delete(2); //s2 = [1], true
    s2.has(2); //flase
    s2.has(1); //true
    s2.clear(); s2 = []
    

36 ES6 - 解构赋值

36.1 解构赋值

  • 快速从对象或者数组中获取成员
  • 分为数组的解构赋值和对象的解构赋值

36.2 解构数组

快速从数组中获取数据

// 以前
let arr['helllo', 'world'];
let a = arr[0];
let b = arr[1];
// 现在
let [a, b] = arr; // a = 'hello', b= 'world'

36.3 解构对象

快速从对象中获取数据
意思是定义了一个变量,这个变量的值对应对象中相同变量名的值。let {name,age}= obj,而let {name:a,age:b}= obj;这种写法就是定义了其他变量名,从冒号前的属性获取值,前一种写法相当于这种写法的简写。

// 以前
let obj = {
	name: 'Jack',
	age: 18
}
let name = obj.name;
let age = obj.age;
// 现在
let {name,age}= obj;
let {name:a,age:b}= obj;

37 ES6 - 字符串

37.1 模板字符串

  • ES6 内新增的定义字符串的方式
  • 用一对反引号``表示字符串
  • 支持换行书写,且字符串会保留换行
  • 可以直接在字符串内解析变量,需要时直接书写 ${ 变量 }
//以前
var a = '123', b = "123"
//现在
var c = `123` 
var d = `1
3`
var h = 3;
var s = `哈哈${h}哈哈` // s = `哈哈3哈哈`

37.2 string 扩展方法

  1. startsWith():表示参数是否在字符串头部,返回布尔值

  2. ensWith():字符串是否以参数结尾 ,返回布尔值

  3. repeat(次数):表示字符串重复的次数,返回新的字符串

    var a = '1234567890';
    var b;
    b = a.startsWith('123'); //true
    b = a.endsWith('0');//true
    b = '123'.repeat(3); //'123123123'
    

38 ES6 - 展开运算符 …,剩余参数…

  • 两个运算符一模一样
  • 作用:展开数组 [] 或者是展开对象();可用合并数组,数组传参,复制对象;在函数定义中对剩余参数的处理
  • 使用示例:
var arr = [ 1,2,3];
console.log(arr);     //[1,2,3]
console.log(...arr);  //1 2 3 这里没有逗号哦

// 合并数组,这样更方便简洁
var arr1 = [1,1,1];
var arr2  =[2,2,2];
var arr3 = [...arr1,...arr2];

// 函数传参
var arr = [2,3,1,5]
var max = Math.max(arr) // NaN
var max = Math.max(...arr)  // 5

//做形参
function fn(a,...b){ };
var fn1 = new fn(1,2,3,4) //a=1,b=[2,3,4]

39 ES6 - 类语法

39.1 类基础

  • 可以用类实例化对象
  • 用 ES6 的语法写构造函数,用法和构造函数一样,class name{ }
  • 类里面的函数不需要加 function,函数之间不要写逗号
  • constructor(),非常重要的函数,是类的构造函数,会把内部的数据返回给实例,new 生成的时候自动调用
  • 但是必须和 new 连用,否则会报错
  • 静态属性和方法必须加上static关键字
  • 类里面所有的属性和方法都是属于实例对象的,类内部使用这些数据的时候必须加上 this 确定
class 类名{
	constructor(){
		// ES5的构造函数
	}
	// 直接写要写在原型上的方法
}

// 示例
class Person{
    constructor(name,age){
        this.name = name;
        this.age = age;
    }
    sayHi(name) {
        console.log(name+' say hello world');
    }
     static a = 100;
    static go() { console.log('running');
}
// 创建类的实例对象必须和new连用
consloe.log(Person.a);
var p1 = new Person('Jack',18);

39.2 类继承

  • 语法:class Son extends Father{ //子类继承父类属性和方法 }

  • 子类继承后可以直接使用父类的属性和方法

  • 注意: 如果子类也想要能够直接传递参数给父类中定义的变量赋值来给父类的函数使用,就必须在子类构造函数中调用super()函数方法,意思是给传递进来的值给父类变量,对应数据用 super 的参数传递

    class Father {
     	constructor(x, y){
            this.x = x;
            this.y = y;
        }
        sum(){
            console.log(this.x+this.y);
        }
    }
    class Son extends Father {
        constructor(x, y){
            super(x, y);
        }
    }
    var a = new Son(1, 2);
    a.sum();
    

39.3 深入理解 super

  • super 实际上就是父类的指代,同样可以用它调用父类函数,语法为 super.sayHi(),这样就可以在子类函数中调用父类函数

  • 子类在构造函数中用 super() 调用父类构造函数,必须把 super 写在自己的构造函数内容之前

    class Son extends Father {
        constructor(x, y){
            super(x, y);
            this.x = x;
            this.y = y;
        }
    }
    

40 前后端交互

40.1 交互

  • 前端:需要的时候把某些内容交给后端,并接收后端返回的信息
  • 后端:主要是连接数据库
  • 交互:后端编程人员会写一个接口文档,前端人员只需要按照接口文档的规范传递信息即可

40.2 交互的实现之一 —— Ajax

基础步骤

  1. 创建 ajax 对象
    var xhr = new XMLHttpRequest()
  2. 配置本次请求信息
    xhr.open(请求方式, 请求地址, 是否异步),这些规范都在接口文档中
  3. 注册完成事件,在请求成功发送,服务器返回数据后执行, xhr.responseText 为后端返回的信息
    xhr.onload = function() { console.log( xhr.responseText ) }
  4. 把请求发送出去
    xhr.send(),只有请求发送出去了,完成事件才有可能执行

返回数据处理

后端通常返回的是 json 格式数据类型,如下

{
	"name": "Jack",
	"age": 18,
	"code": 1
}

我们可以对这种数据进行解析,使用JSON.parse()方法解析

var res = JSON.parse( xhr.responseText ) // 得到的res为对象数据类型

GET 和 POSt 的区别

// GET 携带name和age参数,写在地址后
var xhr1 = new XMLHttpRequest();
xhr1.open('get','hettp://localhost:8888/test/first?name=Jack&age=18',true);
xhr1.onload = function() {
    console.log(JSON.parse(xhr1.responseText));
};
xhr1.send();


// POST 携带参数name和age,参照接口文档的格式,写在send中,需要特殊说明
var xhr2 = new XMLHttpRequest();
// 携带name和age参数
xhr2.open('post','hettp://localhost:8888/test/first',true);
xhr2.onload = function() {
    console.log(JSON.parse(xhr2.responseText));
};
// 特殊说明,说明传参的格式,在接口文档中会标明,如 application/x-wwwxform-urlencoded
xhr2.setRequestHeader('content-type','application/x-wwwxform-urlencoded');
xhr2.send('name=Jack&age=18');

40.3 登录案例

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="utf-8">
    <meta >
    <title>web001</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        ul,ol,li{
            list-style: none;
        }
        html,body{
            height:100%;
        }
       form{
           width: 500px;
           padding: 50px;
           margin: 50px auto;
           border: 5px solid pink;
           display: flex;
           flex-direction: column;
           font-size: 30px;
           padding-top: 50px;
           position: relative;
       }
       form > span{
           position: absolute;
           left:50%;
           top:5px;
           /* 横向居中 */
           transform: translateX(-50%); 
           width: 100%;
           text-align: center;
           color: red;
           font-size: 24px;
           /* 默认不显示 */
           display: none;
       }
       form > label{
           height: 50px;
           text-align: right;
       }
       form > label > input{
           height: 40px;
           font-size: 25px;
           padding-left: 20px;
       }
       form > button{
           width: 80px;
           height: 30px;
           font-size: 18px;
           background-color: lightblue;
           position: absolute;
           bottom: 14px;
           left: 50%;
           transform: translateX(-50%);
       }
    </style>
</head>
<body>
    <form>
        <span class="error">用户名或者密码错误!!</span>
        <label>
            用户名:<input class="username" type="text">
        </label>
        <label>
            密码:<input class="password" type="password">
        </label>
        <button>登录</button>
    </form>
<script>

var loginForm = document.querySelector('form');
var nameInp = document.querySelector('.username');
var pwdInp = document.querySelector('.password');
var errBox = document.querySelector('error');

loginForm.onsubmit = function(e){
    // 注意:要先阻止表单的默认提交行为,才能写自定义的行为
    e.preventDefault();
    console.log("我要提交表单")
    let name = nameInp.value;
    let pwd = pwdInp.value;
    console.log("拿到用户名:"+name);
    console.log("拿到密码:"+pwd);
    if(!name || !pwd) return alert('填写不能为空!');

    // 前后端交互部分
    var xhr = new XMLHttpRequest();
    xhr.open('post','http://localhost:8888/users/login',true);
    xhr.onload = function(){
        var res = JSON.parse(xhr.responseText);
        if(res[code]===1){
            // 这里是跳转
            window.location.href = 'http://www.baidu.com';
        }
        else
            errBox.style.dispaly = 'block';
    }
    xhr.setRequestHeader('content-type','application/x-wwwxform-urlencoded')
    xhr.send('username='+name+'&password='+pwd);
}
</script>
</body>
</html>

41 jQuery

41.0 什么是 jQuery

一个大型的、简单的第三方类库,内部封装了很多常用的类,需要时可用直接调用。

41.1 引入 jQuery

官网地址:https://jquery.com/

  • 方法 1:到官网找到 jQuery.js 文件的地址,复制过来就可以引入该地址就可以
  • 方法 2:到官网把 jQuery 文件下载下来,然后放到项目文件目录下,最后在 html 中引入 jQuery 文件就可以使用了
  • Production version - 用于实际的网站中,是已经被精简和压缩过的 jQuery 文件。
  • Development version - 用于测试和开发中,是未压缩的 jQuery 文件,可以方便阅读源码。
    当引入 jQuery 文件后,会在全局暴露两个变量名,$jQuery,这两个变量是一样的。
<script src="https://code.jquery.com/jquery-3.6.0.js"> </script>
<script src="../jQuery/jquery-3.6.0.js"> </script>

41.2 jQuery 选择器

  • 语法: $('选择器'),返回元素集合
console.log($('li'));
console.log($('ul>li:nth-child(2)'));

41.3 jQuery 筛选器

常用筛选器

  • first():选择器选中的第一个
  • last():选择器选中的最后一个
  • eq(索引):选择器选中的第索引个,从 0 开始
  • next():选择器的后一个
  • nextAll():选择器后面的所有兄弟
  • prev():选择器的前一个元素
  • prevAll():选择器的前面所有兄弟
  • parent():选择器的父元素
  • parents():获取选择器的所有父级结构,知道 html 为止(包括 html)
  • siblings():拿到所有兄弟元素
  • find():拿到所有后代元素中满足选择器要求的元素

41.4 jQuery 操作文本内容

常用

  • html('内容'):等价于原生 js 的 innerHTML,可以获取也可以设置,如果括号呢没有内容,就是获取
  • text():等价于原生 js 的 innerText,用法和 innerHTML 一样。
  • val():等价于原生 js 的 value,使用方法也是可以设置可以获取,主要用来操作表单
$('input').val('新的内容哦');
$('ul').html('<li>新添加一个li</li>');
$('div').html('修改后的div内容');
console.log($('input').val());
console.log($('ul').html());
console.log($('div').html());

41.5 jQuery 操作元素类名

常用

  • addClass('类名'):添加类目
  • removeClass('类名'):删除类名
  • toggleClass('类名'): 切换类名,意思是 有则删除,无则添加
$('div').addClass('b');
$('div').removeClass('a');
$('div').toggleClass('c');

41.6 jQuery 操作元素样式

  • 获取:元素集合.css(要获取的样式名称),可以获取元素的行内样式,也可以获取非行内样式
  • 设置:元素集合.css(样式名,样式值),值为 px 时,px 可用不写, 不写 px 就不用加引号
  • 批量设置:元素集合.css({ 样式名:样式值, 样式名:样式值, 样式名:样式值 })
console.log($('div').css('width')); // 80px
$('div').css('width',200);
$('div').css('background-color','pink')
console.log($('div').css('width')); // 200px

$('div').css({
    'height': '200px',
    'background-color': 'orange'
})

41.7 jQuery 操作元素属性

  • 元素.attr(要获取的属性名,属性值)
    可以获取和设置元素的属性,一般用于操作元素的自定义属性,他操作的所以属性都会出现在元素的标签上

    console.log($('div').attr('hello'));
    $('div').attr('good','good');
    $('div').attr('class','b');
    
  • 元素.remveAttr('要删的属性名')
    删除元素的属性

    $('div').remveAttr('good');
    $('div').remveAttr('class');
    
  • 元素.prop('属性名','要设置的属性值')
    获取和设置元素的属性,
    获取:不能获取元素标签身上的自定义属性,只能获取 prop 方法设置的自定义属性,原生属性没有影响
    设置:当设置原生属性时,会响应在元素标签身上,设置自定义属性时,会响应在元素对象身上

  • 元素.removeProp('属性名')
    只能删除 porp 设置的自定义属性,不能删除原生属性

41.8 jQuery 获取元素属性

  • width():内容

  • innerWidth():内容 + padding

  • outerWidth():内容 + padding+border,如果传参 true,就会加上 margin

  • height():内容

  • innerHeight():内容 + padding

  • outerHeight():内容 + padding+border,如果传参 true,就会加上 margin

    console.log($('div').width());          // 100
    console.log($('div').innerWidth());     // 120
    console.log($('div').outerWidth());     // 140
    console.log($('div').outerWidth(true)); // 160
    

41.9 jQuery 获取元素偏移量

  • offset()
    获取元素相对于页面左上角的坐标位置返回对象数据类型,{top:xxx, left:yyy}
  • position()
    获取元素定位位置,不管设置的什么都会自动转换成 top 和 left

41.10 jQuery 事件绑定

1.on() 方法

  • 基础事件绑定:元素集合.on('事件类型', 事件处理函数)

  • 事件委托绑定事件:元素集合.on('事件类型', 选择器, 事件处理函数),把选择器的事件委托给元素集合绑定

  • 批量绑定事件:元素集合.on({ 事件类型1: 事件处理函数, 事件类型2:事件处理函数 }),这样不能进行事件委托

    $('span').on('click', function() { console.log('点了一下span')});
    $('div').on('click', 'p', function() { console.log('点了一下div里面的p')});	
    $('div').on({
    	click: function(){ },
    	mouseover: funtion(){ }
    })
    

2.one() 方法

on()方法语法一样,但是这种绑定方法只执行一次触发事件。

3.hover() 方法

这是 jQuery 里的特殊事件
语法:元素集合.hover( 移入处理事件函数, 移除处理事件函数)
只有一个函数时移入移出都使用执行这个函数

4. 常用事件函数

  • jQuery 把一些常用事件封装成了函数,需要时直接调用就行,比如 click(), mouseover(), moueseout(), change()

    $('div').click(function(){
        console.log('点了一下div')
    })
    

41.11 jQuery 事件解绑和触发

  • 元素集合.off(事件类型 [, 使劲按处理函数] ):事件解绑,当参数只有事件类型的时候,解绑所有处理函数,也可以再传一个事件处理函数参数,就会解绑对应的处理函数

  • 元素集合.trigger(事件类型):事件触发,通过代码的方式触发

    function fa(){ console.log('我是fa') };
    function fb(){ console.log('我是fb') };
    
    $('div')
        .click(fa)
        .click(fb)
    
    $('div').off('click',fa);
    setInterval( function(){ $('div').trigger('click')},1000);
    

41.12 jQuery 基本动画函数

  1. show():显示

  2. hide():隐藏

  3. toggle():切换——隐藏和显示之间切换

  4. 参数:它们的参数都一样,最多有三个,动画时间、运动曲线、结束回调函数

  5. 它们是同时改变宽高

    $('div').show(1000, 'linear', function(){ console.log('1结束') });
    $('div').hide(1000, 'linear', function(){ console.log('2结束') });
    $('div').toggle(1000, 'linear', function(){ console.log('3结束') });
    

41.13 jQuery 折叠动画函数

  1. slideDown():显示

  2. slideUp():隐藏

  3. silideToggle():切换

  4. 参数:动画时间、运动曲线、结束回调函数

  5. 只改变高度

    $('div').slideDown(1000, 'linear', function(){ console.log('1结束') });
    $('div').slideUp(1000, 'linear', function(){ console.log('2结束') });
    $('div').silideToggle(1000, 'linear', function(){ console.log('3结束') });
    

41.14 jQuery 渐隐渐显动画函数

  1. fadeIn():显示

  2. fadeOut():隐藏

  3. fadeToggle():切换

  4. fadeTo():指定最高透明度,参数:动画时间,透明度,运动曲线,结束回调函数

  5. 参数:动画时间、运动曲线、结束回调函数

  6. 改变透明度

    $('div').fadeIn(1000, 'linear', function(){ console.log('1结束') });
    $('div').fadeOut(1000, 'linear', function(){ console.log('2结束') });
    $('div').fadeToggle(1000, 'linear', function(){ console.log('3结束') });
    $('div').fadeTo(1000, 0.7, 'linear', function(){ console.log('4结束') });
    

41.15 jQuery 综合动画函数

  • animate()综合函数

  • 第一个参数:要运动的样式,以一个对象数据类型传递,对颜色、transform 无效

  • 第二个参数:运动时间

  • 第三个参数:运动曲线

  • 第四个参数:运动结束回调函数

    $('div').animate({
        width: 300,
        height: 300,
        left: 300,
        top: 300,
        'border-radius': '50%'
    },1500,'linear',function(){ console.log('动画结束')})
    

41.16 jQuery 结束动画函数

  • stop():当任何一个元素执行了 stop 方法以后,会立即结束当前所有动画,停留在当前位置;一般用于用于动画开始之前,达到每次触发动画前先清空之前动画的效果。$('div').stop().toggle(2000)
  • finish():立即结束当前所有动画,直接跳到动画结束的效果;用在动画开始之前,会先让之前的动画展示结束状态,再开始这个新动画。$('div').finish().toggle(2000)

41.17 jQuery 的 ajax 请求

  • 发送请求不是 DOM 操作,不依赖选择器获取元素,直接用jQuery或者$变量

  • 语法:$.ajax({ 本次发送ajax的配置项})

  • 配置项:

    1. url:必选,请求地址
    2. method:选填,请求方式,默认 GET
    3. data:选填,表示携带的参数,默认‘ ’
    4. async:选填,表示是否异步,默认 true
    5. success:选填,表示请求成功的回调函数
    6. error:选填,表示请求失败的回调函数
    $.ajax({
        url: 'http://localhost:8888/test',
        method: 'POST',
        async: true,
        data: { name: 'Jack', age: 18 },
        success: function(){
            console.log('请求成功!');
        },
        error: function(){
            console.log('请求失败!');
        }
    })
    

41.18 jQuery 项目案例

没看

42 闭包

42.1 变量及其作用域

  • 变量可以根据作用域不同划分为:全局变量、局部变量

  • 闭包:指有权访问另一个函数作用域中变量的函数。意思是一个作用域可以访问另一个作用域的局部变量。

  • 闭包的作用:在函数外部使用函数内部变量

    function fn(){
    	var num=10;
    	function Star(){
    		console.log(num);
    	}
    	return Star;
    }
    var f = fn(); //return把内部函数给了f
    f();  // 输出 10
    

42.2 闭包应用 - li 标签单独点击输出

var lis = document.querySelect('ol').querySelectAll('li');
for(var i = 0; i< lis.length; i++){
	(function(i){
		console.log(lis[i].innerHTML})(i);
}

43 正则表达式

43.1 定义

  • 定义:正则表达式是用于匹配字符串中字符组合的模式,在 JavaScript 中,正则表达式也是对象。
  • 作用:可以匹配字符串、过滤字符串、提取字符串
  • 特点:灵活性强、功能强,但是比较复杂

43.2 使用

  • 在 JavaScript 中定义:它是对象,可以通过构造函数RegExp来 new 一个,参数就是正则表达式,也可以通过字面量来定义一个, 它一定是/ /的格式。

  • 检验:校验一个字符串是否符合正则表达式的 规定,用正则.test(字符串)方法,这是正则表达式特有的函数方法,

    var rg1 = new RegExp(/123/);
    var rg2 = /123/;
    var c = rg1.test('abc'); //并没有包含123这几个字符
    var d = rg2.test(380);  // false,数字一定是错的
    

43.3 特殊字符

元字符:正则表达式除了有普通的字符,还有一些有特殊意义的字符的专用字符,称为元字符,比如 ^、$。
小括号:只表示优先级

1. 边界符 ^, $

  • ^:表示匹配行首的文本(以谁开始)
  • $:表示匹配行尾的文本(以谁结束)
  • 扩展:^abc$就表示只能是 abc 才 true

2. 字符类 [ ]

  • []:[abc],一系列字符可供选择,只要匹配其中一个字符就 true
  • 扩展:^ [abc]S 就表示只能是其中一个字符才 true
  • [ - ]:方括号内的 - 表示连接到,如 a-d 就是 abcd,这种写法也可以组合,[a-zA-Z0-9_-]
  • [^]:中括号里的^表示取反,和本来意思不一样

3. 量词符:设定模式出现的次数

  • *:相当于 >=0,可以出现 0 次到无数次,用在模式之后,^a*$,这样写 a 可以出现 0 次到无数次,所以这里” “,”a”,“aaaa” 都是 true
  • +:相当于 >=1
  • ?:相当于 1||0,表示允许出现 1 次或 0 次
  • {n}:必须重复 n 次
  • {n,}:重复次数大于等于 n
  • {n,m}:大于等于 n,小于等于 m,中间不要有空格
  • 综合:/^ [a-zA-Z0-9_-]{6,16}$/;就是用户限制在 6 到 16 位只能输入字母数字和 -_的用户 id 正则表达式。

4. 预定义类:某些常见模式的简写方式

  • \d:相当于 [0-9],匹配 0 到 9 之间任意一个数字
  • \D:相当于 [^0-9],匹配 0-9 以外的所有字符
  • \w:相当于 [0-9a-zA-Z_],匹配任意字母数字下划线
  • \W:匹配上一个能匹配的之外的字符
  • \s:匹配空格,包括换行符、制表符、空格符等,相当于 [\r\t\n\v\f]
  • \S:匹配非空格字符

5. 应用

  • 手机号码正则表达式:/^1[34578]\d{9}$/

6. 参数

//switch,switch 就是参数,也称为修饰符,表示正则表达式按照什么样的模式来匹配,有三种:

  • g:全局匹配
  • i:忽略大小写
  • gi:全局匹配 + 忽略大小写
    例:/abc/g 匹配全局所有满足 abc 的,主要用于正则替换

7. 正则替换

意思就是用正则表达式来写要被替换的字符串

var str = '123abc456abc';
// 原来,这样写只能替换第一个abc
var newStr1 = str.replace('abc','QWE');  //'123QWE456abc'
// 现在,加上匹配模式,全局abc都可以替换
var newStr2 = str.replace(/abc/gi,'QWE');  //'123QWE456QWE'
console.log(newStr1+' '+newStr2);

选项卡补充(let 关键字写法)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta >
    <title>Document</title>
    <style>
        *{
            padding: 0;
            margin: 0;
        }
        html,body{
            height: 100%;
        }
        ul,ol,li{
            list-style: none;
        }
        .box{
            width: 600px;
            height: 400px;
            display: flex;
            flex-direction: column;

            margin: 50px auto;
        }
        .box>ul{
            height:60px;
            display: flex;
        }
        .box>ul>li{
            flex: 1;
            display: flex;
            font-size: 30px;
            background-color: pink;
            color: white;
            border: 1px solid palevioletred;
            justify-content: center;
            align-items: center;
        }
        .box>ul>li.active{
            background-color: blueviolet;
        }
        .box>ol{
            flex: 1;
        }
        .box>ol>li{
            width: 100%;
            height: 100%;
            font-size: 100px;
            background-color: skyblue;
            color: white;
            justify-content: center;
            align-items: center;

            display: none;
        }
        .box>ol>li.active{
            display: flex;
        }

    </style>
</head>
<body>
    <div class="box">
        <ul>
            <li class="active">1</li>
            <li>2</li>
            <li>3</li>
            <li>4</li>
        </ul>
        <ol>
            <li class="active">111</li>
            <li>222</li>
            <li>333</li>
            <li>444</li>
        </ol>
    </div>

<script>
	// let ullis = document.querySelectorAll('ul>li');
    // let ollis = document.querySelectorAll('ol>li');
    // for(let i = 0; i< ullis.length; i++){
    //     ullis[i].onclick = function(){
    //         // 先去掉所有样式
    //         for(let j = 0;j< ullis.length; j++){
    //             ullis[j].className = '';
    //             ollis[j].className = '';
    //         }
    //         // 再给自己加样式
    //         ullis[i].className = 'active';
    //         ollis[i].className = 'active';
    //     }
    // }
    class Tab{
        constructor(ele){
            this.box = document.querySelector(ele);
            this.ullis = this.box.querySelectorAll('ul>li');
            this.ollis = this.box.querySelectorAll('ol>li');
        }
        change(){
            let _this = this;
            for(let i = 0; i< _this.ullis.length; i++){
                // 函数封装要注意函数内点击函数内的this指向变了
                _this.ullis[i].onclick = function(){
                    // 先去掉所有样式
                    for(let j = 0;j< _this.ullis.length; j++){
                        _this.ullis[j].className = '';
                        _this.ollis[j].className = '';
                    }
                    // 再给自己加样式
                    _this.ullis[i].className = 'active';
                    _this.ollis[i].className = 'active';
                }
            }
        }
    }
    var box = new Tab('.box');
    box.change();
</script>
</body>
</html>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值