1.获取元素和操作元素
在一般情况下用const声明变量最好,除非是在for循环之类的一定会更改的数据
1.api的作用和分类
分为DOM(文档对象模型)和BOM(浏览器对象模型)
1.DOM
DOM是浏览器提供的一套专门用来操作网页内容的功能,即开发网页内容特效和实现用户交互
2.DOM树
将html文档以树状结构直观的体现出来,称之为文档树或者DOM树
3.DOM对象
浏览器根据html标签生成的JS的对象
dom的核心思想就是把网页内容当对象处理
2.获取DOM元素
1.通过css选择器的方式获取dom元素
格式:document.querySelector(‘css选择器’)
只会选择第一个符合条件的选择器,‘’内可以填入不管多长的css选择器,返回的是一个对象,没有匹配返回Null
如果要选择多个,使用:
document.querySelectorAll(‘css选择器’)
返回的是一个伪数组(即使只有一个元素),一个对象的集合,可以使用遍历数组的方式批量修改
2.操作元素内容
1.修改文字内容
获取对象之后,使用:
对象.innerText = ‘要更换的内容’
显示纯文本,不解析标签
或者:
对象.innerHTML = ‘要更换的内容’
可以解析标签,例如等
2.操作元素常用属性
获取对象之后,使用:
对象.属性 = 值
例如:
img.src = ./1.jpg
3.操作元素样式属性
1.通过style属性修改
先获取元素
元素.style.样式属性 = ‘值’
如果样式属性里有-,则把-后的一个字母改成大写,删除-
记得跟上单位
2.通过类名修改
可以用于修改样式比较多,较繁琐的情况
先获取元素,并且在style里面创建对应的类
元素.className = ‘类名’
使用这个方式会覆盖原先的类,可以使用 ‘原先的类 要加入的类’
3.通过classList修改
先获取元素,并且在style里面创建对应的类
追加:元素.classList.add(‘类名’)
删除:元素.classList.remove(‘类名’)
切换:元素.classList.toggle(‘类名’)
切换就是,有就删除没有就添加
检测:元素.classList.contains(‘类名’)
检测就是,检测这个标签有没有这个类
4.操作表单元素属性
先获取元素,获取表单内的值用的是.value属性不是innerHTML,除了button
修改表单属性:
元素.type = ‘目标属性’
修改表单是否被选择:
元素.checked = true
表示元素被勾选,只能使用布尔值
元素.disabled = true
表示按钮不可以被点击,只能使用布尔值
5.自定义属性
格式:
data-属性名 = “属性值”
调用使用:
元素.dataset.属性名
3.定时器函数
1.间歇函数
开启定时器:
setInterval(函数,间隔时间)
每隔“间隔时间”毫秒(1s=1000ms),调用一次函数,永不停止
可以直接在函数处编辑匿名函数也可以调用编写好的函数,不加小括号
定时器本身返回的是一个id数字,每个定时器都不一样
关闭定时器:
clearInterval(定时器id)
3.事件监听
事件是编程时系统内发生的动作,例如点击一个按钮
事件监听就是让程序检测是否有事件产生,如果触发,就立刻调用一个函数作为响应
代码:
元素对象.addEventListener(‘事件类型’,要执行的函数)
事件类型有:
‘click’ - 点击
‘mouseenter’ - 鼠标经过
‘mouseleave’ - 鼠标离开
‘focus’ - 获得焦点
‘blur’ -失去焦点
‘keydown’ - 键盘按下触发
‘keyup’ - 键盘抬起触发
‘input’ - 用户输入事件
‘change’ - 用户改变了值且离开了文本框
4.事件对象
表示事件触发时的相关信息,例如判断用户按了哪个键,鼠标点击了哪个元素等等
事件监听时,执行函数的第一个参数就是事件对象
元素对象.addEventListener(‘事件类型’,function(e){})
事件对象的属性:
type - 事件对象的类型,例如click,mouseleave
clientX/clientY - 光标相对于可视窗口左上角的位置
offsetX/offsetY - 光标相对于当前dom元素左上角的位置
key - 用户按下的键盘按键值
变量.trim 可以自动删除文本左右多出来的空格,文本中间的空格不变
5.环境对象
指的是函数内部特殊的变量this,代表当前函数运行时所处环境
this指向函数的调用者
如果将函数A作为参数传递给函数B时,函数A成为回调函数
对象的方法里的this指向对象
6.事件流
从外到内的分析事件叫捕获,从内到外反映事件叫做冒泡
1.事件冒泡
当一个元素触发事件后,会依次向上调用同名(例如都是鼠标点击)父级元素的事件
在很多情况下冒泡需要被阻止,一般用阻止冒泡(也可以阻止捕获)
事件对象(就是function里的e).stopPropagation()
2.解绑事件
元素.removeEventListener(‘事件类型’,函数名)
如果是匿名函数无法解绑
如果要阻止默认行为(例如点击a会跳转链接,点击submit会提交)
e(事件对象).preventDefault
3.事件委托
利用事件冒泡,将父元素加上需要统一被调用的效果,就可以减少注册次数,提高程序性能
如果需要对单独的子元素添加效果,可以使用
e(事件对象).target.(tagName)
tagName可以限定在某一种标签内才执行这个效果
例如:if(e.target.tagName == ‘LI’ )
4.页面加载事件
加载外部资源,例如图片,js,外部css等
有些时候需要等页面资源全部处理完之后做一些事情
事件名:
load
监听页面所有资源加载完毕后:
window.addEventListener(‘load’,function(){})
不一定需要等待所有资源加载完毕,就可以针对某个资源添加
如果只等待html完全加载和解析后,不等待样式表和图片加载完毕
可以添加
document.addEventListener(‘DOMContentLoaded’,function(){})
5.元素滚动事件
检测页面滚动条滚动时持续触发的事件
想要丝滑滚动,添加html中的css
scroll-behavior:smooth;
事件名:
scroll
监听整个页面滚动:
window.addEventListener(‘scroll’,function(){})
获取位置:
scrollLeft(页面离最左端被卷去的距离)
scrollTop(页面离最顶端被卷去的距离)
这两个值可读写
如果要读取整个html标签,要使用
document.documentElement
6.页面尺寸事件
检测浏览器尺寸是否变换的事件
事件名:
resize
监听整个页面尺寸变化:
window.addEventListener(‘resize’,function(){})
获取元素宽高:
clientWidth和clientHeight
包括padding,但是不包含margin和border
7.元素尺寸和位置
获取宽高:
offsetWidth和offsetHeight
获取的是可视的宽高,如果盒子隐藏,获取的结果是0
包括border和padding但是不包括margin
获取位置:
offsetLeft和offsetTop
获取元素距离自己定位父级元素的左,上距离
是只读属性,不能写入
获取元素的大小和相对于视口的位置:
element.getBoundingClientRect()
7.日期对象
获取当前时间:
const 日期名 = new Date()
设定时间:
const 日期名 = new Date(‘2022-5-1 08:30:00’)
日期对象方法:
日期名.getFullYear() – 返回本地时间给的年份
日期名.getMonth() – 返回本地时间给的月份(0月-11月 注意加一)
日期名.getDate() – 返回本地时间给的日期
日期名.getDay() – 返回本地时间的星期(周日是星期0)
日期名.getHours() – 返回本地时间给的时
日期名.getMinutes() – 返回本地时间给的分
日期名.getSeconds() – 返回本地时间给的秒
日期名.toLocaleString() – 返回 年/月/日 时:分:秒
日期名.toLocaleDateString()-- 返回 年/月/日
日期名.toLocaleTimeString()-- 返回 时:分:秒
获取date距离1970年1月1日过了多少毫秒(时间戳):
日期名.valueOf(‘时间’)或者日期名.getTime(‘时间’)
也可以:let 日期名 = +new Date(‘时间’)
还有h5新增(兼容差)的方式(不能返回确定的时间):let 日期名 = Date.now()
将时间戳转化为正常时间:
let d = parselnt(总秒数/ 60/60/24); // 计算天数
let h= parselnt(总秒数/ 60/60%24) //计算小时
let m= parselnt(总秒数/60 %60); // 计算分数
let s = parselnt(总秒数%60);//计算当前秒数
8.节点操作
dom树里每个内容都成为节点
节点类型:
元素节点:所有的标签,例如body,div等等
属性节点:所有的属性,例如href
文本节点:所有的文本
1.查找节点
通过关系查找节点,如父,子,兄弟节点
父节点查找:
子元素.parentNode
返回最近一级的父节点,如果没有返回为null,可以叠加返回爷爷,曾爷爷节点
子节点查找:
父元素.children
获取所有下一级子节点标签
兄弟节点查找:
下一个兄弟节点:nextElementSibling
上一个兄弟节点:previousElementSibling
2.新增节点
创建一个新的节点:
document.createElement(‘标签名’)
将创建的元素添加到某个父元素中(成为最后一个子元素):
父元素.appendChild(要插入的元素)
将创建的元素添加到某个父元素的某个子元素前:
父元素.insertBefore(要插入的元素,在哪个元素前面)
3.克隆节点
复制一个原有的节点
元素.cloneNode(布尔值)
如果是true,则复制子代所有元素
如果是false,只复制一级子代元素
4.删除节点
要删除元素,必须通过父元素删除
父元素.removeChild(要删除的元素)
如果不存在父元素则删除无效
5.M端事件
触屏事件:
touchstart – 触摸到一个dom元素时触发
touchend – 手指离开屏幕时触发
touchmove – 手指在元素上滑动触发
9.JS插件
swiper插件,获取别人编写的js文件,直接调用即可
获取完后
css和js文件在package文件夹中
2.浏览器对象模型
1.BOM
window是一个全局对象,是js中的顶级对象,其次是document
所有通过var定义的对象和方法,都会挂靠在window下
2.定时器 - 延时函数
js中内置了一个让代码延迟执行的函数(只执行一次)
let timer = setTimeout(回调函数,等待的毫秒数)
清除延时函数:
clearTimeout(timer)
timer中储存的也是数字型的id
3.location对象
location.herf = ‘网页地址’
跳转到某个地址
location.search
只获取网页表单信息,即网址里?后的内容
location.hash
获取网页#号后的内容
location.reload()
刷新当前页面,括号内加上true则是强制刷新
4.navigator对象
可以检测浏览器版本和运行平台
navigator.userAgent
5.history对象
管理历史记录
history.back()
返回至前一个网页
history.forward()
前进一个网页
history.go(±1)
前进/后退一个网页
6.本地存储
将数据储存在用户浏览器中,大概有5m左右的空间,关闭浏览器不会消失
存储/修改数据:
localStorage.setItem(key,value)
获取数据:
localStorage.getItem(key)
删除数据:
localStorage.removeItem(key)
本地存储只能存储字符串类型
sessionStorage
使用方法同上,但是关闭浏览器后就清空
存储复杂数据类型:
要转化为json字符串:
JSON.srtingify(复杂数据类型)
取回:
JSON.parse(localStorage.getItem(key))
简单数组遍历:
arr.map(function(item,index){
item就是数组元素
index就是索引号
})
数组名.join(分隔符,默认是,)-- 转化为以选定分隔符隔开的字符型
3.正则表达式
用于匹配字符串中字符组合的的模式,JS中,正则表达式也是对象
一般用于:
验证表单(保证用户输入的不是汉字)
过滤敏感词(将敏感词替换成**)
字符串中提取想要的部分(提取)
1.正则表达式语法:
定义正则:const变量名 = /表达式/
判断是否有符合规则的字符串:正则表达式.test(被检测的字符串)
如果匹配返回true,否则返回false
在指定字符串搜索匹配:正则表达式.exec(被检测的字符串)
如果匹配成功,返回的是数组,否则返回Null
2.元字符
平常使用的字母数字被称为普通字符,只能代表其本身
元字符就是拥有特殊含义的字符,例如:
[a-z] – 表示从a~z的26个小写字母
1.边界符
表示位置,开头和结尾,必须用什么开头用什么结尾
^字符 — 表示开头字符
$字符 — 表示结尾字符
如果^字符$,则表示精确匹配,只有输入这个字符才能通过
2.量词
设定某个模式出现的次数,只重复最近的
- – 表示出现0次或更多次
- – 表示出现一次或更多次
? – 表示出现0次或一次
{n} – 表示出现n次
{n,} – 表示出现n次或更多次
{n,m} – 表示出现n次到m次,逗号左右不能有空格
3.字符类
[字符1字符2] – 表示匹配字符集合,只要包含任意一个(只选一个)都返回true,有精确匹配的话只选一个,只能包含一个,要匹配多个需要配合量词
-表示连字符,要在[]内配合使用,比如[a-z]表示全部小写字母,[a-zA-Z]表示大小写全部字母,[0-9]表示0-9的数字
^ – 在中括号内表示取反
.–表示除换行符之外的所有字符
4.预定义类
\d – 匹配0-9之间的任意数字
\D – 匹配0-9以外的任意数字
\w – 匹配任意字母,数字和下划线
\W – 匹配除字母,数字,下划线以外的字符
\s – 匹配空格
\S – 匹配非空格
3.修饰符
约束正则执行的某些行为,比如是否区分大小写,是否多行匹配
格式:/表达式/修饰符
修饰符 i – 表示不区分大小写
修饰符 g – 表示全局匹配,全部都匹配
1.正则替换
字符串.replace(/正则表达式/,‘替换的文本’)
返回新字符串,要用变量接,一般只替换第一个,加上g可以匹配全部
4.JS进阶
1.作用域
作用域分为全局作用域和局部作用域,规定了变量能被访问的范围
1.局部作用域
分为函数作用域和块作用域
函数作用域在函数内部声明且只在函数内有效,函数执行完毕后函数内部的变量实际被清空了
在js中用{}包裹的域称之为块作用域,其中用let和const声明的变量只在块内有效,用var声明的变量可以被外部访问
2.全局作用域
全局作用域可以被其他作用域访问,在script标签和.js文件最外层声明的变量称之为全局变量
尽可能少的声明全局变量,防止变量污染
2.作用域链
作用域链本质上是最底层的变量查找机制
函数被执行时,会优先在当前作用域中查找变量
如果查找不到则依次逐级查找父级作用域,直到全局作用域
子作用域可以访问父作用域,但是父作用域无法访问子作用域
3.垃圾回收机制
JS环境中分配的内存,一般用以下的生命周期:
内存分配:当我们声明变量,函数,对象的时候系统会自动分配内存
内存使用:即读写内存,也就是使用变量、函数
内存回收:使用完毕,由垃圾回收器自动回收不再使用的内存
全局变量一般不会回收(关闭页面)
一般情况下局部变量的值,不用了会自动回收
程序中分配的内存由于某种原因程序未释放或者无法释放叫做内存泄漏
引用计数法清除垃圾:
查看一个对象是否有指向它的引用,没有引用了就回收对象
但是如果两个对象相互引用(循环引用),尽管不再使用也不会回收,导致内存泄露
标记清除法清除垃圾(现代使用):
从根部(就是全局对象)出发定时扫描内存中的对象,如果能从根部到达,则不清除
无法从根部出发触及到的对象会被标记为不再使用,随后回收
4.闭包
简单来说,闭包就是内层函数+外层函数的变量
闭包的作用:让外部也可以访问函数内部的变量
最常见的闭包形式:
function outer(){
let a = 10
function fn(){
console.log(a)
}
return fn
}
outer()
let fun = outer()(就相当于 = fn)
闭包的应用:
实现数据的私有(不会因为全局变量会被覆盖的问题而修改)
闭包内的变量不会被回收,因此可能会造成内存泄漏
5.函数进阶
1.函数提升
函数提升和变量提升类似,函数可以在被声明前调用
但是如果用函数表达式(let fn = function(){})的方式,则无法提升
2.函数参数
1.动态参数
属性:arguments
是伪数组,里面储存的是用户传递过来的所有实参,只存在于函数中
(伪数组有索引号有下标但是没有数组常用的方法)
2.剩余参数
属性:…变量名
是真数组,里面储存的是用户传递过来的实参的未被形参接住的部分
使用的时候不需要写…
3.展开运算符(补充)
符号:…
可以将数组展开,不会修改原数组,一般用于求数组最大/小值(Math.max/min(…arr)),合并数组(const newArr = […arr1,…arr2])等
3.箭头函数
可以写更简短的函数且不绑定this,替代函数表达式,适用于本来需要匿名函数的地方
写法:const 变量名 = (形参) => {函数体}
(就是省略了function,加上了=>)
只有一个形参的时候可以省略小括号
只有一行代码的时候可以省略大括号和return
例如:const fn = x => x + x
箭头函数还可以直接返回一个对象,但是要加上小括号
例如:const fn = (uname) => ({ uname: uname })
1.箭头函数的参数
箭头函数没有arguments,但是有…变量名
箭头函数的this沿着作用域链指向上一层作用域的this
对象方法中的this:箭头函数没有this,方法的上一层是其他函数或者对象,其他函数或者对象是谁调用的,this就指向谁
4.解构赋值
1.数组解构
数组解构是将数组的单元值快速批量的赋给一系列变量的简洁语法
语法:const [变量名1,变量名2,…] = 数组或者[数组元素1,数组元素2,…]
典型应用于交换两个变量
let a = 1
let b = 2;
[b, a] = [a, b]
一定要加分号
当变量多单元值少的情况下:
多出来的部分是undefined
当变量少单元值多的情况下:
多出来的部分没有被赋值,可以用剩余参数将多出来的部分以数组的方式存储
const [a, b, ...c] = [1, 2, 3, 4]
c=[3,4]
防止 undefined 传递可以给变量设定默认值:
const[a=0,b=0] = [1]
如果数组内又不需要的部分可以留空:
const [a, b, , d] = [1, 2, 3, 4]
d=4
多维数组也可以解构:
const [a, b, c] = [1, 2, [3, 4]]
c=[3,4]
如果要输出单独的:
[a, b, [c, d]] = [1, 2, [3, 4]]
2.对象解构
对象解构是将对象的属性和方法快速批量的赋给一系列变量的简洁语法
语法:
const {变量名1,变量名2} = 对象或者{属性/方法1,属性/方法2}
变量名和属性名必须相等
对象中找不到与变量名一致的属性时变量值为undefined
对象解构的变量名可以改名:
旧变量名: 新变量名
例如:const { uname: username, age } = { uname: ‘pink老师’, age: 18 }
解构数组对象:
const [{ uname, age }] = 数组对象
多级对象解构:
const { 一级属性名: { 二级属性名, 二级属性名, 二级属性名 } } = 对象名
5.构造函数和数据常见函数
创建对象的三种方式:
利用字面量创建对象
const 对象名 = {}
利用new object创建对象
const 对象名 = new Object({})
利用构造函数创建对象:
可以快速创建多个类似的对象
封装一个函数
function 构造函数名一般大写字母开头 (形参){
this.属性名 = 形参
}
调用
const 对象名 = new 构造函数名(实参)
构造函数内不需要return
构造函数的步骤:
1.创建新的空对象
2.构造函数this指向新对象
3.执行代码,修改this,添加新的属性
4.返回新对象
实例成员:
构造函数创建的对象成为实例对象,实例对象的属性和方法成为实例成员
静态成员:
构造函数中的属性和方法称为静态成员
构造函数中的this指向构造函数
1.内置构造函数
字符串,数值,布尔等基本类型也有专门的构造函数,js几乎所有的数据都可以基于构造函数创建
引用类型有:
Object,Array,Regexp,Date等
简单类型有:
String,Number,Boolean等
1.Object构造函数
获得所有属性名
Object.keys(对象名) 返回一个数组
获得所有属性值
Object.values(对象名) 返回一个数组
对象深拷贝,复制一个一样的对象,后赋值前,主要用于对象添加属性
Object.assign(被添加数据的对象,需要拷贝的对象)返回一个对象
2.Array构造函数
forEach遍历数组
遍历数组的每个元素
语法:被遍历数组.forEach(function(当前数组元素,当前元素索引号){
函数体
})
与map的不同在于不返回值,类似于一个简单版for循环
filter筛选方法
筛选数组符合条件的元素并且返回筛选后的新数组
数组名.filter(function (元素, 索引号){
return 筛选条件
}
map迭代函数
返回新数组,返回的是处理后的数组元素
语法:
const 新数组 = 被遍历数组.map(function(当前数组元素,当前元素索引号){
函数体
})
reduce累计器
返回累计处理的结果,经常用于求和等
数组名.reduce(function(上一次值,当前值){},初始值)
初始值就是最开始的上一次值,省略初始值,上一次值就是数组的第一项
find返回第一个匹配测试函数的元素的值,否则返回undefined
数组名.find(function(item){
return 筛选条件
},)
filter用于数字的判断,find用于寻找元素
every检测方法,如果所有元素满足返回true
数组名.every(function(item){
return 筛选条件
},)
更多补充:
伪数组转换为真数组:
const 真数组名 = Array.from(伪数组名)
3.String构造函数
split方法,将字符串转化为数组(与join相反)
const arr = str.split(‘分隔符’)
substring方法,返回一个字符串从包括开始索引到不包括结束索引
const newStr = str.substring(开始索引,(结束索引))
如果省略结束索引就是到最后一个,与数组的slice相似
startsWith方法,检测是否以某字符串开头,同理有endWith
str.startsWith(‘字符串’,(开始位置))
include方法,判断一个字符串是否包含在另一个字符串中,返回布尔值
str.include(‘字符串’,(开始位置))
3.Number构造函数
toFixed方法,保留n位小数,四舍五入,没有则补0
num.toFixed(小数位数)
6.面向对象
面向对象是把事物分解成一个个对象,然后由对象之间分工合作
面向对象是以对象功能来划分问题,而不是步骤因此灵活,代码可复用,适用于多人合作的大型软件项目
在js中最直观的体现面向对象的思想就是构造函数
但是构造函数有浪费内存的问题,特别是其中的方法
7.原型
构造函数通过原型分配的函数对所有对象共享
格式:构造函数.prototype
这个原型对象不会多次创建,可以吧不变的方法直接定义在prototype上
原型对象里面的函数this指向的还是实例对象
包括JS自带的构造函数也可以添加原型
例如:Array.prototype
constructor(构造器)属性
该属性指向原型对象的构造函数
constructor:构造函数名
如果用重新赋值的方式覆盖原来的prototype,使用这个重新指回原来的构造函数
每个对象都有一个 __proto__对象原型属性指向构造函数的原型对象
_proto_不是一个标准属性 有时浏览器渲染成[[Prototype]]
是一个只读属性,不能修改
对象原型中也有一个constructor属性,指向构造这个对象的构造函数
1.原型继承
原型继承对象是继承对象的地址,如果往某个原型内写入数据,会使所有调用此对象的原型全部改变
一般用构造函数使每个继承的对象结构相同但地址不同
2.原型链
规则1:只要是对象就有__proto__
规则2:只要是原型对象就有constructor
instanceof方法
对象名 instanceof 属性名
返回布尔值
8.深浅拷贝
浅拷贝只针对引用类型,拷贝的是地址
1.拷贝对象: Object.assgin(需要的对象,被复制对象) /展开运算符{…obj}
2.拷贝数组: Array.prototype.concat() 或者[…arr]
比起直接复制,不会影响原来的对象/数组的简单数据类型
但是对于对象套对象等情况,还是会复制内部的地址
因此需要进行深拷贝
-
通过递归实现
-
lodash/cloneDeep
3.通过JSON.stringify()实现
1.函数递归
自己调用自己称之为递归函数
可以使用对轨函数实现setTimeout模拟setInterval的效果
function deepCopy(newObj, oldObj) {
for (let k in oldObj) {
// 处理数组的问题 一定先写数组 再写 对象 不能颠倒
if (oldObj[k] instanceof Array) {
newObj[k] = []
deepCopy(newObj[k], oldObj[k])
} else if (oldObj[k] instanceof Object) {
newObj[k] = {}
deepCopy(newObj[k], oldObj[k])
}
else {
newObj[k] = oldObj[k]
}
}
}
2.js库lodash
lodash库里有cloneDeep方法
引用方法:const newobj = _.cloneDeep(需要拷贝的对象)
3.利用json
用JSON.parse(JSON.stringify(被复制对象))
即转化为字符串再转换为对象
9.异常处理
1.throw
throw可以传递一个错误,程序会中止执行
格式:throw new Error(‘错误内容’)
2.try/catch/finally
try要配合catch和finally使用
try{
尝试的内容
}
catch(err){
//返回浏览器提供的错误信息
console.log(err.message)
}
如果尝试的内容错误,会返回错误信息并且会正常执行下面的代码
finally{
执行内容
}
finally不论程序执行是否错误,一定会执行
3.debugger
断点调试,是关键字直接输入就好
10.this
普通函数this谁调用指向谁,严格模式下指向undefined
箭头函数this指向一层一层向上查找上级作用域的this
原型对象和需要用到this的dom对象都不推荐使用箭头函数
1.改变this的指向
call()方法:
使用call方法调用函数,修改this的指向
函数名.call(this的指向,参数1,参数2)
apply()方法:
使用apply方法调用函数,
函数名.apply(this的指向,[实参1,实参2])
函数用形参1,形参2接收
可以用来求数组最大值等
Math.max.apply(this的指向,数组)
bind()方法:
bind不会调用函数,返回值是函数,this是更改过的
函数名.bind(this的指向,参数1,参数2)
11.防抖和节流
防抖就是单位时间内,频繁触发事件,只执行最后一次,可以优化性能
一般用于搜索框输入,手机验证,邮箱验证等等
节流就是单位时间内频繁触发事件,只执行一次,直到事件执行完成
一般用于高频事件,例如鼠标移动(mousemove),页面尺寸缩放(resize)等等
1.lodash防抖
_.debounce(函数,默认时间)
即等待默认时间后调用一次函数
2.防抖函数逻辑
声明一个定时器变量
每次触发的时候先判断有没有定时器,有的话先清除定时器再开
如果没有定时器啧开启定时器并且存到变量中
时间到了调用一次函数
例子:
function debounce(fn, t) {
let timeId
return function () {
// 如果有定时器就清除
if (timeId) clearTimeout(timeId)
// 开启定时器 200
timeId = setTimeout(function () {
需要调用的函数
}, t)
}
}
3.lodash节流
_.throttle(函数,默认时间)
即等待默认时间后才可以重新调用函数
4.节流函数逻辑
声明一个定时器变量
每次触发的时候先判定有没有定时器,有则不开启新定时器
如果没有则开启定时器
定时器内调用执行的函数并且清空定时器
例子:
function throttle(fn, t) {
let timer = null
return function(){
if(!timer){
timer = setTimeout(function(){
fn
timer = null
},t)
}
}
5.视频事件
视频.ontimeupdate = 函数
视频时间变化时执行函数
视频.currentTime
获得视频当前时间
视频.loadeddata = 时间
将视频跳转到时间