闭包: 函数嵌套函数,内部函数就是闭包;
体会闭包
function outerfun(x){
function innerfun(y){
console.log(x + y);
}
return inner; //没有小括号,表示只输出inner函数的定义,不会立即执行
}
var i = outerfun(3);
/* 其实这个时候
i = innerfun(y){
console.log(3 + y)
}
*/
i(5); //8
经典案例:
function outer() {
let a = 10;
function inner() {
console.log(a);
}
return inner; //没有小括号,表示只输出inner函数的定义,不会立即执行
}
console.log(outer()); //inner函数
var fun = outer(); //fun 内部存储的是inner函数的地址。
/* 相当于function inner() {
console.log(10)
}*/
fun() //10
闭包: 内部函数没有执行完,外部函数的变量不会被销毁。
闭包的应用?
可以封装一段代码,模块化
//原来的写法
let a = 10;
let b = 20;
function add() {
return a + b;
};
function sub() {
return a - b;
}
let res1 = add();
let res2 = sub();
console.log(res1);
console.log(res2)
封装后的写法:
// 封装后的写法,模块化
let module = (function () { //自执行函数
let a = 10;
let b = 20;
function add() {
return a + b;
};
function sub() {
return a - b;
}
return {
// add: add,
// sub: sub,
add, //es6的简写语法
sub,
}
})()
let res1 = module.add();
let res2 = module.sub();
console.log(res1);
console.log(res2);
防抖: 用户触发时间过于频繁,只要最后一次事件的操作;
比较好理解但是很烂的代码哈哈哈,下面有封装好的代码;
let ipt = document.querySelector("input");
// ipt.oninput = function(){
// console.log(this.value); //过于频繁触发
// }
// 定义一个全局的计时器time
let time = null;
ipt.onchange = function(){
// 判断,time是计时器的返回值,如果time不是null,就清掉计时器;
if(time !== null){
clearTimeout(t);
}
t = setTimeout(()=>{
console.log(this.value);
}, 500)
}
封装好的防抖代码:
let ipt = document.querySelector("input");
ipt.onchange = debounce(function(){
// console.log("hello 防抖--闭包");
console.log(this.value); //使用 fn.call(this)后,这里的this指向发生改变
}, 500)
function debounce(fn, delay){
let time = null; // 定义一个计时器time
return function(){
// 判断,time是计时器的返回值,如果time不是null,就清掉计时器;
if(time !== null){
clearTimeout(t);
}
t = setTimeout(()=>{
// console.log(this.value); //这里的this指向input
// fn(); //
fn.call(this); //直接调用fn()即可,但是同时还要改变this的指向,所以使用fn.call(this);
}, delay)
}
}
节流:控制执行次数;
区别防抖:是只执行最后一次;
节流的现象:
给body标签设置,鼠标滚动一下,就会触发一次;
<style>
body{
height: 50000px;
}
</style>
window.onscroll = function(){
console.log(124);
}
控制节流的代码:
// 节流: 控制执行次数
// 最开始flag是true, if判断为true执行,执行一次后,设置为true,500毫秒执行一次;
let flag = true
window.onscroll = function(){
if(flag) {
setTimeout(()=>{
console.log(123);
flag = true;
}, 500)
}
flag = false;
}
封装的节流代码:
// 封装节流的代码
window.onscroll = throttle(function(){
console.log("hello");
}, 500)
function throttle(fn, delay){
let flag = true
return function(){
if(flag) {
setTimeout(()=>{
// console.log(123);
fn.call(this);
flag = true;
}, delay)
}
flag = false;
}
}
节流: 在一定的时间内,执行一
次,控制次数;
防抖: 高频发事件,只执行最后一次;
课程讲解:
https://www.bilibili.com/video/BV1E44y1z7XL
https://www.bilibili.com/video/BV1HK4y1g7fA
https://www.bilibili.com/video/BV1Qo4y1Q7AN/?spm_id_from=autoNext