ECMAscript 基础语法
变量 数据类型 运算符 数组 函数 对象
BOM 浏览器对象模型
window对象(获取浏览器宽高)
history对象
location对象
DOM 文档对象模型 轮播图
元素获取 操作属性 操作样式 节点 事件 时间对象
作用:(运营在用户端浏览器)
1. 数据验证
2. 动态创建和删除元素
3. 操作元素的内容和样式
4. 模拟动画
5. 创建cookie
6. ajax 请求数据
。。。。。。
7. JSON格式的数据处理 *
特征:面向对象
1. 基于[对象]和[事件驱动]的松散型 解释型语言
2. 客户端脚本语言,实现用户交互
BOM: 浏览器对象模型
完成窗口与窗口之间的通信,window对象是其核心对象,
•history【前进,后退,刷新】 是一个对象 使用【window.history】
•location【地址】
•DOM【】
•screen【屏幕】
•frames[真窗口]
•navigation
window对象:
属性
1-1:获取浏览器宽高
a.ie8及以上
window.innerWidth [获取浏览器宽度]
window.innerHeight [获取浏览器高度]
b.ie8以下
document.documentElement.ClientWidth [宽度]
document.documentElement.ClientHeight 【高度】
1-2: 重新获取浏览器宽高
window.onreset=function () {
NewW=window.innerWidth;
NewH=window.innerHeight;
}
1-3:重新设置浏览器大小
window.onresize=function(){
}
1-4:浏览器滚动事件
window.onscroll=function (){
}
2.浏览器左上角距离屏幕左上角的偏移量
window.screenTop [垂直偏移量]
window.screenLeft [水平偏移量]
注意:
因为window是核心,可以省略window不写
方法
alert() 弹出框
prompt() 输入框
confirm() 提示框,返回true或flase
close() 关闭页面
open(“url”) 打开页面(“打开的页面的路径【根据本html位置的相对路径】”)
open("url","","width=300,height=200");
setInterval(fn,毫秒数):隔毫秒数重复不断的执行一个函数fn
方法1
let t =setInterval(fn,3000)
function fn(){
}
方法2
setInterval(function(){
},1000)
clearInterval(t):清除setInterval的时间函数
let t =setInterval(fn,3000)
function fn(){
}
clearInterval(t)
setTimeout(fn,1000) 隔一定的时间只执行一次函数
cleanTimeout(t) 清除时间函数 【用法同上】
获取表单的值
对象.value=
清空=“”
history对象
属性:
history.length 用来显示历史记录的长度
方法
history.forward() 前进
history.back()后退
history.go(0) 刷新 【1 前进,-1后退;不常用】
location对象
属性:设计获取当前页面的地址
location.href=“ ” 设置或获取页面地址 设置新值
location.host:主机名+端口号
location.hostname:主机名
location.port:端口号
location.protocol:协议
location.pathname: 路径
location.search: ?后面的查询【搜索】字段
方法
location.reload( ) 重新加载
location.replace("网页.html") 页面替换,不会增加历史记录
location.assign(“网页.html”) 页面替换, 能够增加历史记录
DOM(文档对象模型)document object model
获取元素
获取body:document.body
获取html:document.documentElement
1. 获取id名的元素:
let 变量=document.getElementById("id名")
例子: let box=document.getElementById("id名")
2.获取class名的元素[得到的是集合,可以通过键名访问]
let 对象=document.getElementsByClassName(“class名”)
通过遍历改变样式
集合通过单个下表改变,不能全部用class名同时改变
3. 获取标签名的元素[得到的是集合,可以通过键名访问]
let 对象=document.getElementsByTagName(“标签名”)
4.给对象加类
标签加1个类名
对象.className=“类名”
div加多个类名
对象.className=“类名1 类名2 ”
5.指定范围的多层级获取【集合】
<div class="box">
<div class="box1">
<div class="box2"></div>
</div>
</div>
多楼层获取
let box=document.getElementClassName("box");
let box1=box.getElementClassName("box1");
let box2=box1.getElementClassName("box2")
6.获取选择器选中的元素
let liss=document.querySelector("【选择器】"); 获取选择器选中的第一个元素
let lis=document.querySelectorAll("【选择器】"); 获取选择器选中的全部元素【集合】【下标或者foreach遍历】
7.属性选择器
<textarea name="con" id="text" cols="30" rows="10"></textarea>
let con = document.querySelector("[name=con]")
操作样式
获取样式
获取行内样式
对象.style.样式名
获取通用的样式【css和行内】
getComputedStyle(对象,null).样式名
设置行内样式
对象.style.样式名=“样式值”
对象.style=“background:red;border-radius:50%”
批量操作类名
对象.className="class类名"
对象.className=“ ”;
对象.classList.add(“”) 添加类
对象.classList.remove(“”) 删除类
对象.classList.toggle(“”) 切换类
对象.id="id名"
外部定义一个样式,加到对象身上,参考第四点
操作属性
操作标准属性
已知的,系统自带
对象.属性
例子 : img.src
自定义属性
获取
对象.getAttrbutte("name")
设置
对象.setAttrbutte("name","value")
操作内容
innerText:不能识别html的标签对
innerHTML: 可以识别html的标签对
对象.innerText=“内容”
对象.innerHTML=“内容”
添加事件
对象.对象事件=function(){
}
元素的尺寸和位置
对象.offsetWidth:获取元素的真实宽度
对象.offsetHeight:获取元素的真实高度
对象.offsetTop:对象的上边框距离具有定位的父元素的内边框的垂直距离
对象.offsetLeft:对象的左边框距离具有定位的父元素的内边框的水平距离
对象.scrollTop:有滚动条的元素,浏览器滚动时在垂直方向的拉动距离
body的兼容
document.body.scrollTop || document.documentElement.scrollTop
对象.scrollLeft:有滚动条的元素,浏览器在滚动时在水平方向的拉动距离
动态创建标签
let div=document.createElement(“标签名”)
创建的元素放到也面中:
document.body.appendChild(div)
父元素.appendChild(子元素)
引入JS
1. 外部引入方式
<head>
<script src='路径'></script>
</head>
2. 内部引入方式(在html页面中放入srcipt标签,和body同级)
<script>
</script>
3. 放在事件后
<div onclick="alert(1)">文字等或事件</div>
注意:
~js的几种引入方式是相互关联的,可以相互操作与访问
~外部js中不能添加srcipt标签对
~嵌入式的js中不能添加src属性
引入js的执行
1. 将srcipt标签对放最最后
2.在.js文档中加入
window.onload=function(){
需要执行的js代码块
}
输出工具
弹出框:alter(' '); 数字可加可不加' ';
输出到控制台:console.log('输出到控制台');
输出到html页面中[可以识别html的标签对,即解释为html语言]:document.write('<h1>输出到html页面中 </h1>');
输入工具
弹出框输入:var num=prompt("提示文本",[默认值]);
提示工具
confirm("提示内容");
confirm返回值为true和false
注释
单行注释: ctrl+?或者/ //
块注释: ctrl+shift+/或者? /* 块 */
拼接
1. 用“+”拼接
2. 模板字符串(es6):
`<td>${i}-${j}</td>`; 拼接部分用``括起来,变量用 ${变量}
识别空格,换行等
变量
一个容器,存储数据
变量的声明:
var:
let:
let命令,用来声明变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效
1. 适用于for循环
2. 先声明,在使用
3. 不允许在相同作用域内重复声明同一个变量。
4. let可以识别块级作用域
5. 不存在变量提升(先访问后声明) 报错:没有定义
const
声明一个只读的常量。一旦声明,常量的值就不能改变。
声明常量的同时进行赋值,不赋值就会报错
可以识别块级作用域
不能重复声明
不存在变量提升【先访问在声明】
PI;
命名规范:
•数字。字母。下划线组成
•不能以数字开头
•区分大小写
•不能以关键字(js中已经用到的)命名
•不能以保留字(js中将来会用到的)命名
•有意义
•遵循的规则:首字母大写 (Array String Obiect) ;驼峰命名法 (getElementByld)
赋值
•先声明再赋值
var num;
num=10;
•声明的同时赋值
var num=10;
•一次性声明多个变量,再赋值
var a,b,c;
a=1,b=2;
c=3;
•一次性声明多个变量同时复制
var a=1,b=2,c=3;
注意事项:
•变量要先声明再访问,变量的默认值是undefined
•新值可以覆盖旧值
•变量可以用var关键字重新声明
•不用var关键字声明时必须给变量赋值,并且为全局变量,先访问后声明变量,值为undefined:js执行时先预解析(即识别var 和function声明的变量,不赋值),在解析,一句一句执行。
数据类型
根据在内存中的存储位置划分。基本数据类型存放在栈中,引用数据类型存放在堆中(指针存放在栈中,内容存放在堆中 )
基本数据类型
•undefined
•null 【空占位符】
•string 【也是对象】
模板字符串 字符编码 ASCII utf-8 unicode【万国码】 gb2312
转义字符: \ \n[换行] \r \t[制表符] \' \ ""
let 对象=new String(“ ”);
编码
对象.charCodeAt(2) 返回第2个位置的字符编码
String.fromCharCode(字符编码) 解码
查找元素
对象.charAt(0) 字符串的第0个位置的元素【查找字符】
查找下标
对象.indexOf(“ ”) 查找对应字符的下标,如果有返回下标,如果没有,返回-1【第一个字符开始的下标】
对象.lastIndexOf(“”) 倒着看查找,倒序看如果有返回下标,如果没有,返回-1【第一个字符开始的下标】
对象.search(“”) 正则:有返回0;没有返回-1;
对象.match(“”) 有的话,返回数组【返回值,下标,包含返回值的数组,】
没有 返回null
字符串的截取:【返回新值,不改变原内容】
对象.substr(开始下标,【截取的长度】)
对象.substring(开始下标,结束的下标),从开始下标开始到结束下标之前,不取到结束的下标
对象.slice(开始下标,结束的下标),从开始下标开始到结束下标之前,不取到结束的下标【数组的方法】
字符串大小写【转换】
let str="AbCdEf";
str.toLowerCase() 转换为小写
str.toUpperCase() 转换为大写
替换:
str.replace(“山”,“闪”);
转换【字符串转换数组】
let str=“1,2,3,4,5,6”;
arr2=str.split(“,”);
•boolean
•number 2e3=2*10^3
二进制: 0b开头
八进制:以0o{0+字母o}开头,后跟0-7的数
十六进制:以0x开头,后跟0-9或者a-f
NaN:not a number 本来期望返回数值的操作,但并未返回数值的操作
引用数据类型
•object(属性与方法的集合)数组,函数,对象
•深拷贝
let arr=【1,2,3,4】
let arr1;
arr1=arr; :传址
arr1 和 arr具有相同地址
•浅拷贝:
let arr=【1,2,3,4】
let arr1=【】
arr.foreach(function(value){
arr1.push(value)
})
判断变量的数据类型 ,其结果为字符串
typeof用法:
var num="5555";
typeof num;
数据类型
值
情况
typeof 的结果【看返回0 1代码的前三位】
undefined undefined undefined
null null(空占位符) object
boolean 布尔型 true false boolean
string 字符串型 带" "或者' ' string
number 数值型 整数,小数,八进制,十六进制,十进制
object
运算符
表达式:能够求值的语句
算术运算符
+ - * / % ++var var++ --var var --
+的特殊性
计算:操作对象是数值型
拼接:操作对象含有字符串,字符串中进行运算时,用()括起来
自增与自减
++var: ++在前,先算++,在执行本行的其他语句
var++:++在后,先执行本行的其他语句,在算++
关系运算符
返回值为布尔值 ,即true或者false
> < >= <= ==[等于] ===[全等于]--> 数值和数据类型相同 !=[不等于] !==[不全等]
•如果比较的两个对象都是字符串[数字型,字符],按照ASCII表对应的ASCII码比较,逐位相比
•如果比较的两个对象都是数值,直接比大小
•如果一个操作对象是字符串,另一个是操作对象是数值,先尝试将字符串转换为数字,如果转换成功,按照数字比较大小;如果转换不成,则返回false
•1==true; 0==false ; ==数值相同
•=== 数值和数据类型相同
•undefined=null
赋值运算符
= +=[num+=10 等价于 num=num+10] -= *= /= %=
逻辑运算符[与或非]
测量值与变量之间的逻辑关系
假:0、false undefined null NaN “ ”【空字符串】
真:其余为真
•&&与
•||或
•!非【用来取反】
A
B
A && B
A || B
!A
true true true true false
true false false true false
false true false true true
false false false false true
返回值:
第一步:先看与或非两边的真假
第二步:在看返回的真假的内容
&& 同真为真,返回第一个假值 【遵循短路原则:看到假值,后边的不看了】;全为真,返回最后一个真值
|| 同假为假,返回第一个真值 【遵循短路原则:看到真值,后边的不看了】;全为假,返回最后一个假值
! 取反;返回值只有ture或false
运算符的优先级
算术>关系运算符>逻辑运算符
三元运算符:
表达式?为真的执行语句:为假的执行语句 【类似if else】
一元运算符: typeof + - new
特殊运算符: () .
流程控制
代码按照指定条件的执行顺序
•顺序结构
•分支结构
•循环结构
顺序结构
语句按照从上到下的顺序进行执行
循环结构
当满足条件时,重复不断的执行一段代码
for循环:明确知道次数
for(初始条件;终止条件;步进值){
}
swith循环
switch(表达式【能够求值的语句】){
case 值1【表达式能取到的值】:语句1;break;
case 值2【表达式能取到的值】:语句2;break;
...
default: 语句;
}
while循环
while(条件){
满足条件时,执行语句;
}
例子:
var j=0;
while(j<5){
console.log(1);
j++;
}
do while循环
执行顺序先执行循环体,在执行判断语句
do{
循环体;
}while(条件)
例子:
var i=0;
do{
console.log(1);
i++;
}(i<5)
循环结束
continue
满足条件终止本次循环
break
满足条件,终止整个循环
分支结构
当条件成立时执行相应的语句
•单分支结构
if条件:
if(表达式){
为真的执行语句【返回值为true执行的语句】
}
•双分支
if条件:
if(表达式){
为真的执行语句
}
else{
为假的执行语句
}
•多分支
if条件:
if(表达式1){
表达式1成立时执行语句
}
else if(表达式2){
表达式1不成立 但 表达式2成立时执行语句
}
else if(表达式3){
表达式1不成立且表达式2不成立【但】表达式3成立时执行语句
}
else{
以上表达式都不成立时执行的语句
}
•嵌套分支
if(){
if(){
}
else{
}
}
else{
}
数学方法
取随机数
Math.random() ; (0-1)
取整
向下取整【向左取整】: rgb=Math.floor(Math.random());
向上取整【向右取整】: rgb=Math.ceil(Math.random());
次幂[x的y次幂]
Math.pow(x,y)
一维数组
按照顺序排列的一组相关数据。
特点:每一个数组元素都有一个特定的键名(即俗称的下标)[字符串类型]
数组元素的默认值时undefined
数组的声明[初始化数组]
•先声明后赋值
var arr=[];
arr[0]=89,arr[0]="adc",....;
•声明的同时赋值
var arr=[90,89,88,76,56];
数组下标的范围
访问数组元素,范围【0,n-1】
数组的长度
数组名.length; 例子: arr.length
注意:
数组的长度可变
arr=[90,89,88,76,56];
可以随时添加元素,可跳着添加。如:
arr[6]="aaa";
数组元素可以时任意的数据类型
arr=[true,null,{name:},[1,2,3]]
遍历数组元素
访问数组的每一个元素
1. 用for循环遍历数组
for(var i=0;i<arr.length;i++){
arr.[i]; 即可访问arr的每个元素
}
2. 用for in循环遍历数组
for(var i in arr){
i; //代表arr的键名(下标)
arr[i]; //元素
}
3.for of遍历元素
for(item of arr1){
arr2.push(item)
}
4.foreach遍历数组
用法:
arr.forEach(function (value,index){
})
value[名字随便起]:数组中的当前元素【必须有】
index[名字随便起]:数组当前元素的下标【键名】【可选】
清空数组
arr.length=0
二维数组
声明:
var arr=[[1,2.3],["a","b"],[78,89];
访问:
arr[行][列]
遍历
for(var i=0;i<arr.length;i++){
for(var j=0;j<arr[i].length;j++){
arr[i][j]
}
}
数组身上的方法
向数组的后面插入一个或多个元素(.push)
arr.push(需要插入的内容);
删除数组最后一位:.pop
arr.pop()
在数组之前插入: .unshift
arr.unshift("")
在数组之前删除一位:.shift
arr.shift()
万能的插入和删除:.splice()
arr.splice(开始的位置,长度,“再删除的位置加入的元素1”,“再删除的位置加入的元素2”,...);
不想删除,让其长度为0;
可以返回删除的值:arr.splice()
是否包含某个元素: .includes
arr.includes(“被包含的内容”);
截取元素: .slice
arr.slice(2,5):截取第2位开始的。第5位之前的
连接多个数组:.concat
arr.concat([数组1],[数组2])
数组的取反:.reverse
arr.reverse()
把数组转换为字符串: .join
arr.join(“连接符(-/,/;/..)”)
排序:.sort
arr.sort((x,y)=> x-y); 升序
arr.sort((x,y)=> y-x); 降序
arr.sort(function(x,y){
return x-y
})
查找: .find()
arr.find(item=>item>7) 找到第一个比7大的数
arr.find(item=>item%2==0) 找第一个偶数
arr.find(function(item){
return item%2==0;
})
查找第一个符合条件的下标: .findIndex()
let index= arr.findIndex(function(item){
return item > top //返回布尔值,为真时返回下标
})
返回符合条件的真假值:.some()
arr.some(item=>item>8);
返回每一个符合条件的元素:.every()
arr.every(item=>item<10);
筛选符合条件的:.filter()
arr.filter(item=>item%2==0); 返回新数组
遍历数组(.forEach)
arr.forEach
用法:
arr.forEach(function (value,index){
})
value[名字随便起]:数组中的当前元素【必须有】
index[名字随便起]:数组当前元素的下标【键名】【可选】
处理每个元素:.map
arr.map(item=>{return item*10}) //让数组中的每个元素都执行一个函数,返回一个新数组
全部方法
concat()
连接两个或更多的数组,并返回结果。
copyWithin() 从数组的指定位置拷贝元素到数组的另一个指定位置中。
every() 检测数值元素的每个元素是否都符合条件。
fill() 使用一个固定值来填充数组。
filter() 检测数值元素,并返回符合条件所有元素的数组。
find() 返回符合传入测试(函数)条件的数组元素。
findIndex() 返回符合传入测试(函数)条件的数组元素索引。
forEach() 数组每个元素都执行一次回调函数。
indexOf() 搜索数组中的元素,并返回它所在的位置。
join() 把数组的所有元素放入一个字符串。
lastIndexOf() 返回一个指定的字符串值最后出现的位置,在一个字符串中的指定位置从后向前搜索。
map() 通过指定函数处理数组的每个元素,并返回处理后的数组。
pop() 删除数组的最后一个元素并返回删除的元素。
push() 向数组的末尾添加一个或更多元素,并返回新的长度。
reduce() 将数组元素计算为一个值(从左到右)。
reduceRight() 将数组元素计算为一个值(从右到左)。
reverse() 反转数组的元素顺序。
shift() 删除并返回数组的第一个元素。
slice() 选取数组的的一部分,并返回一个新数组。
some() 检测数组元素中是否有元素符合指定条件。
sort() 对数组的元素进行排序。
splice() 从数组中添加或删除元素。
toString() 把数组转换为字符串,并返回结果。
unshift() 向数组的开头添加一个或更多元素,并返回新的长度。
valueOf() 返回数组对象的原始值。
函数
把实现某一特定功能的代码块封装起来,并能够重复调用
定义函数
1. 基本语法(function关键字)【调用可以在声明前,也可以在声明后】
function 函数名(形参1,形参2,....){
函数体;
return 返回值;【可有可无】 《并不向用户显示,仅是调用的数的值》
}
2. 字面量,自变量【必须先声明在调用】【预解析】
var 变量=function (参数){
函数体;
}
调用 变量()
3. 对象的方式【实例化对象】
let aa=new Function(“a”,“b”,“alter(a+b)”)
调用 aa(10,20)
匿名函数定义与调用
(function (){
})()
定义:(function (){
}
调用【一般在定义的时候就调用】:
(function (){
})()
箭头函数
定义:
let aa=()=>console.log(123);
let aa=(参数)=>{
多行函数体;
}
调用:
aa(实参)
函数的调用
1. 函数名(实参1,实参2,….)
2. 自变量()
3.自变量(参数1,参数2)
参数
能够动态改变函数体的变量,使函数更加灵活
形参:
定义函数使写在括号里的量。其作用为接收实参
形参默认值的传递
1. if else分支结构
if(flag==undefined){
}
else{
}
2. 三元运算符【用的多】
flag=flag==underfined?"<":flag
3. 逻辑或||返回第一个真值【用的多】
flag=flag||"<"
4. 定义形参的时候直接赋值:当形参为undefined时给形参默认值
flag=25555;
实参:
函数调用时写在括号中的值。其作用为给形参传值
全部的实参由arguments接收
参数传递
•参数可以是任意的数据类型
•参数的传递按顺序传递:从左到右
•形参=实参 :一一对应的传递
•形参>实参:多余的形参赋值为undefined
•形参<实参:实参由arguments对象来接收
剩余参数
声明: ...rest【为数组】
function 函数名(形参1,...rest){
函数体;
}
rest和arguments对象的区别
1. rest接收多余的参数,arguments接收全部的实参
2. rest是数组,能够使用数组的方法,键名从0开始;
arguments对象类似数组,不能使用数组的方法
函数的返回值:return
return 终止函数。遇到return,后面都不执行
返回值可以是任意的数据类型
一个函数内部可以有多条return分支语句,但最终只执行一条return语句
只能返回一个值
回调函数
把一个函数的指针(函数名)作为参数传递给另一个函数,当指针调用函数时,这个函数叫做回调函数【高阶函数】:形参高阶函数和 返回值高阶函数
指针类型
function math(num1,num2,callback) {
return callback(num1,num2);
}
function add(num1,num2) {
return num1+num2;
}
function sub(num1,num2) {
return num1-num2;
}
function mult(num1,num2) {
return num1*num2;
}
function div(num1,num2) {
return num1/num2;
}
document.write(math(1,2,div));
函数类型
foreach
arguments对象
用来接收参数的详细信息
每声明一个函数,在其内部自动生成arguments对象
arguments对象只在函数内部起作用
不是数组类似数组,可以用键名遍历数组(arguments[i]),其长度为arguments.length
不能用数组身上的方法
闭包函数
内部的函数调用外部的函数的【变量】;
function fn1(){
let a="456";
function fn2(){
console.log(a)
}
return fn2;
}
let fn2=fn1();
fn2()
// js中没有函数的重载:传的参数不同,执行不同的函数
作用域
变量起作用的范围
局部作用域优先于全局作用域[作用域链]
•全局作用域
1. 在整个js中都能访问的变量,凡是进行修改,变量的值就会改变
2. 类型【情况】
在函数外部用var声明的变量,即拥有全局作用域
不用var声明,但是赋值的变量就是全局变量,即拥有全局作用域;
•局部作用域
类型【情况】
形参是局部变量,即拥有局部作用域
在函数内部用var关键字声明的变量,也是局部变量,即拥有局部的作用域。
•块级作用域
{
括起来的就是块级作用域;
}
内置顶层函数
内置:ECMAscript自带的函数,本身就有;只要求知道如何让使用,不用关心如何封装
顶层:在js代码中的任何位置都可以使用;
escape():将传进来的字符串进行编码
escape("编码的内容"); 编码内容一般为中文
unescape():对编码的字符串进行解码
unescape("字符串的编码")
Boolean():将其余数据类型转换为布尔型
String():将任意数据类型转换为字符串型
Number():将其余数据类型转换为数值型
情况
1. null:0 “”:0 “ ”:0
2. false:0 true:1
3. undefined:NaN
4. 进制数转换为十进制
5. 去掉没有意义的后导0和前导0
6. 字符串: 规范的浮点数,数值型字符串
parseInt():将字符串转换为整数
第一个位置为字母 (+、-)号 空格
转换不成功,转换为NaN
parseFloat():将字符串转换为小数
只能转换规范的浮点数
转换不成功,返回NaN
isNaN():值是否够转换为数值型
能转换为数值型返回false
不能转换为数值型返回true
作用:数据类型转换
强制类型转换
隐式数据类型转换:算数运算符,逻辑运算符,条件语句(if,while等)
对象 类
概念
类:一群具有相同特征的对象集合的描述
对象:具体存在的类个体
属性:对象基础信息的描述
方法:对象功能的描述
定义对象
构造函数(类),实例化对象
1. 构造类
function 类名(color,price等其他形参){
this.color=color;
this.price=price; //实例化时,this指向实例化的对象
this.play=function(){
}
}
2. 实例化对象
let 对象=new 类名(实参);
3. 对象的属性【对象属性的添加】
对象.属性名=“属性值”; 访问:对象.属性名 / 对象【‘属性名’】
4. 对象的方法【对象方法的添加】【方法是特殊的属性】
对象.方法名=function(){}; 访问:对象.方法名()
5. 遍历【i代表的是属性名】
for(let i in 对象){
i;//属性名,方法
对象【i】;//属性值
}
6. 对象属性的增删改查:
增加: 对象.属性名=“属性值”;
删除: delete 对象.属性名
修改: 对象.属性名=“属性值”
查讯: 对象.属性名 ; 对象【‘属性名’】
JSON [注意格式] 【可直接定义对象】
1.定义
let 对象={
属性名:属性值, //属性名可以加引号,也可以不加引号
属性名:属性值,
方法名:function(){
},
方法名:function(){
}
}
2.增删改查
增加: 对象.属性名=“属性值”;
删除: delete 对象.属性名
修改: 对象.属性名=“属性值”
查找: 对象.属性名 ; 对象【‘属性名’】
3.遍历
for(let i in 对象){
i;//属性名,方法
对象【i】;//属性值
}
4.对象.constructor 返回 object
class定义类,实例化对象
重要的关键字[方法]
constructor: 返回该对象的构造函数
使用: 对象.constructor
instanceof:判断函数是否为对象的构造函数?true:false;
使用 : 对象 instanceof 构造函数
原型,原型链
最大的类:object:[prototype proto]
生成人类:person:【proto prototype】 proto继承父类的prototype
生成对象:xb【proto,prototype】 proto继承人类的prototype
sing改变函数的指针
sing.call(xb,10,20)
sing.apply(sb,【10,20】)
sing.
将小白的say方法传给小红
say=xh.say
say.call(xh)
递归
函数自己调用自己,必须有一个 出口
function fn(num){
if(num==0){
return 1;
}
else{
return num*fn(num-1)
}
}
function fnn(arr){
let arr1=[]
for(let i=0;i<arr.length;i++){
if(typeof arr[i]=="object"){
arr1.push(fnn(arr[i]))
}
else{
arr1.push(arr[i])
}
}
return arr1;
}
console.log(fnn([0,[1,2],[2,3]]))
节点:
整个文档 元素【标签】 属性 文本 注释【节点】
文档的节点
document.nodeName #document
document.nodeValue null
document.nodeType 9
元素的节点
let box=documentquerySelector("box")
box.nodeName 大写的标签名
box.nodeValue null
box.nodeType 1
节点
nodeName(名字)
nodeValue(值)
nodeType(节点类型)
文档节点 #document null 9
元素节点 大写的标签名 null 1
属性节点 大写的属性名 属性值 2
文本节点 #text 文本 3
注释节点 #comment 注释内容 8
节点的获取
1.childNodes:子节点
document.childNodes[1].childNodes
2.parendNode:父节点
let box=document.querySelector("box") ;
3.上一个兄弟节点:previousSibling
box.previousSibling
3.下一个兄弟节点:nextSibling
box.nextSibling
4.上一个兄弟元素节点:previousElementSibling
box.previousElementSibling
5.下一个兄弟元素节点:nextElementSibling
box.nextElementSibling
节点的方法
创建元素节点
let div=document.createElement("div")
在最后插入节点
let box=document.querySelector(“.box”);
box.appendChild(div)
在之前插入节点.insertBefore(要插入的元素,插入位置之后的元素)
let span=document.querySelector("span")
box.insertBefore(span,div)
创建文本节点
let text=document.createTextNode("必须有参数")
text.nodeValue=“这是span标签”
span.appendChild(text)
创建注释节点
let comment1=document.createComment(“这是注释节点”);
box.appendChild(comment1);
创建属性节点
let attr=document.createAttribute("id");
添加/设置属性节点
.setAttribute("name","value");//添加属性
box.setAttributeNode(attr)
添加:append 删除:remove
删除标签节点 : box.removeChild(div)
删除属性节点: box.removeChild(“属性名”)
DOM(文档对象模型)document object model
获取元素
获取body:document.body
获取html:document.documentElement
Dom对象
1. 获取id名的元素:
let 变量=document.getElementById("id名")
例子: let box=document.getElementById("id名")
2.获取class名的元素[得到的是集合,可以通过键名访问]
let 对象=document.getElementsByClassName(“class名”)
通过遍历改变样式
集合通过单个下表改变,不能全部用class名同时改变
3. 获取标签名的元素[得到的是集合,可以通过键名访问]
let 对象=document.getElementsByTagName(“标签名”)
4.给对象加类
标签加1个类名
对象.className=“类名”
div加多个类名
对象.className=“类名1 类名2 ”
5.指定范围的多层级获取【集合】
<div class="box">
<div class="box1">
<div class="box2"></div>
</div>
</div>
多楼层获取
let box=document.getElementClassName("box");
let box1=box.getElementClassName("box1");
let box2=box1.getElementClassName("box2")
6.获取选择器选中的元素
let liss=document.querySelector("【选择器】"); 获取选择器选中的第一个元素
let lis=document.querySelectorAll("【选择器】"); 获取选择器选中的全部元素【集合】【下标或者foreach遍历】
7.属性选择器
<textarea name="con" id="text" cols="30" rows="10"></textarea>
let con = document.querySelector("[name=con]")
操作样式
获取样式
获取行内样式
对象.style.样式名
获取通用的样式【css和行内】
getComputedStyle(对象,null).样式名
设置行内样式
对象.style.样式名=“样式值”
对象.style=“background:red;border-radius:50%”
批量操作类名
对象.className="class类名"
对象.className=“ ”;
对象.classList.add(“”) 添加类
对象.classList.remove(“”) 删除类
对象.classList.toggle(“”) 切换类
对象.id="id名"
外部定义一个样式,加到对象身上,参考第四点
操作属性
操作标准属性
已知的,系统自带
对象.属性
例子 : img.src
自定义属性
获取
对象.getAttrbutte("name")
设置
对象.setAttrbutte("name","value")
操作内容
innerText:不能识别html的标签对
innerHTML: 可以识别html的标签对
对象.innerText=“内容”
对象.innerHTML=“内容”
添加事件
对象.对象事件=function(){
}
元素的尺寸和位置
对象.offsetWidth:获取元素的真实宽度
对象.offsetHeight:获取元素的真实高度
对象.offsetTop:对象的上边框距离具有定位的父元素的内边框的垂直距离
对象.offsetLeft:对象的左边框距离具有定位的父元素的内边框的水平距离
对象.scrollTop:有滚动条的元素,浏览器滚动时在垂直方向的拉动距离
body的兼容
document.body.scrollTop || document.documentElement.scrollTop
对象.scrollLeft:有滚动条的元素,浏览器在滚动时在水平方向的拉动距离
动态创建标签
let div=document.createElement(“标签名”)
创建的元素放到也面中:
document.body.appendChild(div)
父元素.appendChild(子元素)
BOM: 浏览器对象模型
完成窗口与窗口之间的通信,window对象是其核心对象,
•history【前进,后退,刷新】 是一个对象 使用【window.history】
•location【地址】
•DOM【】
•screen【屏幕】
•frames[真窗口]
•navigation
window对象:
属性
1-1:获取浏览器宽高
a.ie8及以上
window.innerWidth [获取浏览器宽度]
window.innerHeight [获取浏览器高度]
b.ie8以下
document.documentElement.ClientWidth [宽度]
document.documentElement.ClientHeight 【高度】
1-2: 重新获取浏览器宽高
window.onreset=function () {
NewW=window.innerWidth;
NewH=window.innerHeight;
}
1-3:重新设置浏览器大小
window.onresize=function(){
}
1-4:浏览器滚动事件
window.onscroll=function (){
}
2.浏览器左上角距离屏幕左上角的偏移量
window.screenTop [垂直偏移量]
window.screenLeft [水平偏移量]
注意:
因为window是核心,可以省略window不写
方法
alert() 弹出框
prompt() 输入框
confirm() 提示框,返回true或flase
close() 关闭页面
open(“url”) 打开页面(“打开的页面的路径【根据本html位置的相对路径】”)
open("url","","width=300,height=200");
setInterval(fn,毫秒数):隔毫秒数重复不断的执行一个函数fn
方法1
let t =setInterval(fn,3000)
function fn(){
}
方法2
setInterval(function(){
},1000)
clearInterval(t):清除setInterval的时间函数
let t =setInterval(fn,3000)
function fn(){
}
clearInterval(t)
setTimeout(fn,1000) 隔一定的时间只执行一次函数
cleanTimeout(t) 清除时间函数 【用法同上】
获取表单的值
对象.value=
清空=“”
history对象
属性:
history.length 用来显示历史记录的长度
方法
history.forward() 前进
history.back()后退
history.go(0) 刷新 【1 前进,-1后退;不常用】
location对象
属性:设计获取当前页面的地址
location.href=“ ” 设置或获取页面地址 设置新值
location.host:主机名+端口号
location.hostname:主机名
location.port:端口号
location.protocol:协议
location.pathname: 路径
location.search: ?后面的查询【搜索】字段
方法
location.reload( ) 重新加载
location.replace("网页.html") 页面替换,不会增加历史记录
location.assign(“网页.html”) 页面替换, 能够增加历史记录
事件
事件的添加方式
节点.onclick=function(e){
}
只能添加一个
节点.addEventListener("事件【click】",事件处理程序,事件类型【布尔值】【可以不给】)
可以添加多个事件
将事件加在元素身上, 在js中定义事件的函数
<body>
<div class="son" onclick="事件函数()"></div>
</body>
<script>
function 事件函数(){
函数体
}
</script>
事件的构成
事件源:谁去触发事件谁就是事件源
事件:鼠标事件/键盘事件
事件处理程序:
常用的web端事件
onclick:单击
ondblclick:双击
onmousedown:按下
onmouseup:抬起
onmousemove:鼠标移动
onmouseover:移入
onmouseout:移出
onmouseenter:移入
onmouseleave:移出
oncontextmenu:右击事件【默认事件】
对象.oncontextmenu=function(e){
e.preventDefault() //阻止浏览器默认右击行为
}
onmousewheel 滚轮滚动事件
移动端事件
ontouchstart:按下
ontouchmove:移动
ontouchend:抬起
事件对象:
用来保存事件触发时的信息
w3c : 在事件处理程序的形参中
ie : 在window.event中
解决兼容性:let event=e || window.event
鼠标事件对象常用的属性:
clientX : 距离浏览器 X轴 的偏移量 【client设备】
clientY:距离浏览器 Y 轴 的偏移量
从 浏览器的 哪个位置进来
offsetX:距离事件源 X轴 的偏移量
offsetY:距离事件源 Y轴 的偏移量
从 事件源的 哪个位置进来
screenX:距离屏幕 X轴 的偏移量
screenY:距离屏幕 Y轴 的偏移量
从 屏幕的 哪个位置进来
键盘事件
onkeydown 键盘按下
onkeyup 键盘抬起
onkeypress键盘按下:按下功能键ctrl shift alt delete esc等不会触发
键盘事件对象常用的属性
keyCode:键盘码
ctrlKey:是否按下了ctrl
shiftKey:是否按下了shift
altKey:是否按下了alt
key:键名
表单事件
oninput:输入事件
onchange:内容发生改变,并且失去焦点
onblur:失去焦点
onfocus:获得焦点
onsubmit:提交表单
onselect:文本选中
窗口事件
onscroll:滚动事件
onload:加载
onresize:重新获取浏览器大小
事件流
当触发一个事件时,由这个事件的容器到整个文档都会按照特定的顺序依次进行触发
顺序:子元素 -》 父元素 【具体的到不具体的】
事件分类
捕获型事件:true【大到小,不具体的事件源到具体的事件源】
冒泡型事件:false【小到大,具体的事件源到不具体的事件源】
浏览器执行事件的顺序:doc的捕获 html的捕获 body的捕获 具体元素的捕获 具体元素的冒泡 body的冒 泡html的冒泡 doc的冒泡
阻止事件流
w3c浏览器
box.addeventListener(“click”,function(event){
let event=event|| window.event
event.stopPropagation()
},false)
ie浏览器
box.addeventListener(“click”,function(event){
let event=event|| window.event
event.stopPropagation()
event.returnValue=true;
},false)
事件委派
event.target:目标事件源【记录】获取到的是元素/属性:类型:节点;点谁获取到谁
event.target.className 事件源的类名
正则
定义
用来描述或者匹配一系列符合某种规则的字符串,规则可以自己定义
作用
•数据验证
•内容检索
•内容替换
•内容过滤
正则对象
创建正则对象
实例化对象
let reg = new RegExp("正则表达式[即规则]","模式修正符")
必须传入字符串
自变量,字面量
let reg=/正则表达式/模式修正符 ; (//代表定界符)
正则对象常用的方法
test(str) 检测正则对象是否能够匹配str , 返回值 true || false
exec( str ) 检测正则对象是否能够匹配str,如果能够匹配,返回一个拥有特殊属性的数组,如果不能匹配,返回null
let reg = new RegExp("uek","gi");
let bool=reg.test("IT培训认准优逸客,专注品质IT教育,成就IT高薪就业 - 优逸客官网"); //bool=true
正则表达式
原子
原子:正则表达式最小的内容【只能匹配一位】
\d 匹配 0-9 ;
\D 匹配:除了0-9意外的字符
\w 匹配:数字、字母、下划线
\W 匹配:除了数字字母下划线以外的字符
\s 匹配:空白 \n换行 \r回车 \t 制表符
\S 匹配:除了空白以外的字符
\b 单词的边界
\B 非单词边界
let str=“abc1”
let reg=/\w/g;
reg.test(str)
原子表【只匹配一个】
定义: [ ]
匹配a-c
let str=“abcdef1”
let reg=/[a-c]/g;
reg.test(str)
匹配 [a-z] 匹配a-z
匹配 [a-zA-Z] 匹配a-z和A-Z
匹配 [a-zA-Z0-9] 匹配a-z和A-Z和0-9
匹配 [a-zA-Z\s] 匹配a-z和A-Z和空格
元字符
. 代表所有的字符
| 或者
原子组
相当于变量默认保存在内存中;可以使用\1 \2等方式依次引用()中的内容
(?: )可以使原子组不在内存中存储,不可以调用
let str1="山西优逸客"
let str2="陕西优逸客"
let reg=/(山西|陕西)优逸客/g;
reg.exec(str1)
let str="<div>hello</div>"
let reg=/<(div)>hello<\/\1>/g
reg.exec(str);
let str="<div>div</div>" //没有变量名
let reg=/<(div)>\1<\/\1>/g
reg.exec(str);
let str="<div>山西优逸客-山西</div>"
let reg=/<(div)>(山西|陕西)优逸客-\2<\/\1>/g
let reg=/<(div)>(?:山西|陕西)优逸客-\2<\/\1>/g \2不会被引用
数量[手机号/身份证号]
* 0个或者多个 》=0 贪婪
let phone="18335219360";
let reg=/\d*/g
reg.exec(phone)
+ 1个或者多个 》=1
? 0个或者一个 吝啬
{11}限制长度为11
{15,18} 长度为 15-18
{6,} 长度为6以及以上
贪婪吝啬 +? 变成吝啬
*?
+?
{11,}?
{11,20}?
边界判断【限制长度】
^ 以...开始
$ 以...结束
let reg=/^(0351)-\d{7}$/
let str1="hello word"
let reg=/o\b/
模式修正符
可以搭配使用 gi mi mg 先后顺序执行
g 全局 global
记录下标,下一个下标位置开始
i 不区分大小写
m 可以换行
正则的使用场所
1.正则对象
2.str对象 中的 str.split(正则对象) 拆分
let str="山西有一棵:1,2.3"
str.split(/[: , .]/)
3.str对象 中的 str.replace(正则对象) 替换
let str="山西有课山西有了"
str.replace(/(山西)/g,陕西)
4.str对象 中的 str.search(正则对象) 查找
let str="山西有课山西有了"
str.search(/(山西|有一颗)/)
常用的正则
用户名 /^[a-z0-9_-]{3,16}$/
密码 /^[a-z0-9_-]{6,18}$/
十六进制值 /^#?([a-f0-9]{6}|[a-f0-9]{3})$/
电子邮箱 /^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$/
/^[a-z\d]+(\.[a-z\d]+)*@([\da-z](-[\da-z])?)+(\.{1,2}[a-z]+)+$/
URL /^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/
IP 地址 /((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)/
/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/
HTML 标签 /^<([a-z]+)([^<]+)*(?:>(.*)<\/\1>|\s+\/>)$/
删除代码\\注释 (?<!http:|\S)//.*$
Unicode编码中的汉字范围 /^[\u2E80-\u9FFF]+$/
日期对象/函数
自定义时间
let ay=new Date("2018/8/8 12:00:00")
let ay1=new Date("12:00:00 2018/8/8")
let ay2=new Date("2018,0,8") //月份从0开始
获取当前格林尼治时间
let now=new Date() //获取当前格林尼治时间
now.setFullYear(2020) 设置年份
now.setMonth(5) 6月份
now.setDate(26) 26号
now.setHours(12) 12时
now.setMinutes(0) 分
now.setSeconds(0) 秒
now.setMilliseconds(0) 毫秒
获取世界协调时间【用法同上】
now.setUTCFullYear()
now.setUTCMonth()
now.setUTCDate()
now.setUTCHours(12) 12时
now.setUTCMinutes(0) 分
now.setUTCSeconds(0) 秒
now.setUTCMilliseconds(0) 毫秒
//获取时间
now.getFullYear() //now.getUTCFullYear()
now.getMonth()+1
now.getDate()
now.getDay() 星期
now.getHours()
now.getMinutes()
now.getSeconds()
now.getMilliseconds(0)
//获取毫秒数
now.getTime() 1970.1.1.0的毫秒数
时间案例
倒计时
jishi()
setInterval(jishi,2000);
function jishi(){
let arr=daoJiShi();
span9.forEach(function (value,index) {
value.innerText=arr[index];
})
}
function daoJiShi() {
let arr=[];
let now=new Date();
let future=new Date(2018,6,26,18);
let times=future.getTime(); //未来的毫秒数
let time=now.getTime();//现在的毫秒数
let juXianZai=Math.floor((times-time)/1000); //2018.9.1到现在时间的秒数
let Month=Math.floor(juXianZai/(30*24*60*60));
arr.push(Month);
juXianZai=juXianZai%(30*24*60*60);
let Day=Math.floor(juXianZai/(24*60*60));
arr.push(Day);
juXianZai=juXianZai%(24*60*60);
let shi=Math.floor(juXianZai/(60*60));
if(shi>0 & shi<9){
shi="0"+shi;
}
arr.push(shi);
juXianZai=juXianZai%(60*60);
let fen=Math.floor(juXianZai/(60));
if(fen>0 & fen<9){
fen ="0"+fen;
}
arr.push(fen);
let miao=Math.floor(juXianZai%60);
if(miao>0 & miao<9){
miao="0"+miao;
}
arr.push(miao);
return arr;
}
}
轮播图
双下标
window.onload=function () {
let Box1=document.querySelectorAll("div.box .box1"); //5个小盒子盒子
let box=document.querySelector("div.box"); //大盒子
let Width=parseInt(getComputedStyle(box,null).width); //小盒子的宽度
let Left=document.querySelector("div.box .left"); //左右两个盒子
let Right=document.querySelector("div.box .right");
let circle=document.querySelector("div.box .circle"); //小圆圈
let Son=document.querySelectorAll("div.box .circle .son");//小点
console.log(Box1,Width,Left,Right,Son);
let now=0;
let next=0;
flag=true;
let t=setInterval(move2,2000);
//右向左
function move2() {
next++;
if(next==Box1.length){
next=0;
}
// 就绪
Son[next].classList.add("son1");
Son[now].classList.remove("son1");
Box1[next].style.left=Width+"px";
//动画
animate(Box1[next],{left:0});
animate(Box1[now],{left:-Width},function () {
flag=true;
});
now=next;
}
//左向右
function move3() {
next--;
if(next<0){
next=Box1.length-1;
}
//就绪
Box1[next].style.left=-Width+"px";
Son[next].classList.add("son1");
Son[now].classList.remove("son1");
//动画
animate(Box1[next],{left:0});
animate(Box1[now],{left:Width},function () {
flag=true;
});
now=next;
}
box.onmouseenter=function () {
clearInterval(t);
}
box.onmouseleave=function () {
t=setInterval(move2,2000)
}
Left.onclick=function () {
if(flag==false){
return;
}
if(next==0){
return;
}
flag=false;
move3();
}
Right.onclick=function () {
if(flag==false){
return;
}
if(next==Box1.length-1){
return;
}
flag=false;
move2();
}
Son.forEach(function(value,index){
value.onclick=function(){
if(index==now){
return;
}
else if(index>now){
Son[index].classList.add("son1");
Son[now].classList.remove("son1");
//就绪
Box1[now].style.left=-Width+"px";
Box1[index].style.left=0;
}
else if(index<now){
Son[index].classList.add("son1");
Son[now].classList.remove("son1");
//就绪
Box1[now].style.left=Width+"px";
Box1[index].style.left=0+"px";
}
now=next=index;
}
})
}
单下标
tupian下包含 a a下包含img
tupian x y 同级
let tupian = daohang.getElementsByClassName("tupian")[0];
let a1 = tupian.getElementsByTagName("a");
let img = tupian.getElementsByTagName("img");
let z = daohang.getElementsByClassName("z")[0];
let y = daohang.getElementsByClassName("y")[0];
let x = daohang.getElementsByClassName("x")[0];
let Son = x.getElementsByClassName("son");
num = 0;
let t = setInterval(move, 2000);
function move() {
num++;
if (num == img.length) {
num = 0;
}
for (let i = 0; i < img.length; i++) {
a1[i].style.zIndex = 20;
Son[i].className = "son";
}
Son[num].className = "son son1";
a1[num].style.zIndex = "30"
}
img.onmouseenter = function () {
clearInterval(t)
}
img.onmouseleave = function () {
t = setInterval(move, 2000)
}
tupian.onmouseenter = function () {
clearInterval(t);
}
tupian.onmouseleave = function () {
t = setInterval(move, 2000);
}
z.onclick = function () {
a1[num].style.zIndex = 20;
}
y.onclick = function () {
move();
}
for (let i = 0; i < Son.length; i++) {
Son[i].onclick = function () {
for (let j = 0; j < Son.length; j++) {
Son[j].className = "son";
}
a1[i].style.zIndex = "40";
Son[i].className = "son son1";
num = i;
}
}
function move1() {
num--;
if (num < 0) {
num = a1.length - 1;
}
for (let j = 0; j < a1.length; j++) {
a1[j].style.zIndex = 20;
Son[j].className = "son"
}
Son[num].className = "son son1"
a1[num].style.zIndex = 30;
}
z.onclick = function () {
move1();
}
透明度轮播
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>轮播</title>
<script src="jquery-3.2.1.js"></script>
</head>
<style>
*{
padding:0;
margin:0;
list-style: none;
}
height: 250px;
width: 500px;
margin: 0 auto;
position: relative;
}
div.box .imgbox{
height: 100%;
width: 100%;
position: relative;
}
div.box .imgbox div{
height: 100%;
width: 100%;
position: absolute;
top:0;
left:0;
opacity: 0;
}
div.box .imgbox .active{
opacity: 1;
}
div.box .next{
height: 50px;
width: 15px;
position: absolute;
right: 0;
top:50%;
margin-top:-25px;
background: black;
opacity: 0.8;
}
div.box .pre{
height: 50px;
width: 15px;
position: absolute;
left: 0;
top:50%;
margin-top:-25px;
background: black;
opacity: 0.8;
}
div.box ul{
height: 10px;
width: 50px;
position: absolute;
bottom:25px;
right:25px;
display: flex;
justify-content: space-between;
align-items: center;
}
div.box ul li{
height: 10px;
width: 10px;
border-radius: 50%;
background: white;
}
div.box ul .active{
background: #b0b0b0;
}
</style>
<body>
<div class="box">
<div class="imgbox">
<div class="active" style="background: red;"></div>
<div style="background: green;"></div>
<div style="background: yellow;"></div>
</div>
<div class="next"></div>
<div class="pre"></div>
<ul>
<li class="active"></li>
<li class=""></li>
<li class=""></li>
</ul>
</div>
</body>
</html>
<script>
$(function(){
let num=0;
let t=setInterval(move,2000);
function move(type="next"){
if(type=="next"){
num++;
}else if(type=="pre"){
num--;
}
if(num>=$("div.box .imgbox div").length){
num=0
}
if(num<0){
num=$("div.box .imgbox div").length-1
}
$("div.box .imgbox div")
.removeClass("active")
.eq(num).addClass("active")
$("div.box ul li")
.removeClass("active")
.eq(num).addClass("active")
}
$("div.box .pre").click(function(){
move("pre")
})
$("div.box .next").click(function(){
move()
})
$("div.box").hover(function(){
clearInterval(t)
},
function(){
t=setInterval(move,2000);
})
$("li").click(function(){
let a=$(this).index();
$("div.box .imgbox div")
.removeClass("active")
.eq(a).addClass("active")
$("div.box ul li")
.removeClass("active")
.eq(a).addClass("active")
num=a
})
})
</script>