JS知识点汇总(四)--闭包&浏览器缓存

1.闭包是什么?作用是什么?有哪些特性?有什么使用场景和注意事项呢?

1、闭包是什么

闭包是由函数以及声明该函数的词法环境组合而成的。这个说法来源于MDN-闭包。
还有种说法:闭包是指有权访问另外一个函数作用域中的变量的函数。

function foo() {
    var a = 1;
    return function() {
        console.log(a);
    }
}

var bar = foo();
bar();

foo()函数的执行结果返回给bar,而此时变量a仍在使用,还没被销毁,然后执行bar()函数。这样我们就能在外部作用域访问到函数内部作用域的变量。这个就是闭包。

闭包产生的必要条件是

  • 存在函数嵌套;
  • 嵌套的内部函数必须引用在外部函数中定义的变量;
  • 嵌套的内部函数必须被执行。

2.闭包的作用

  • 可以读取函数内部的变量
  • 可以使变量的值长期保存在内存中,生命周期比较长。
  • 可用来实现JS模块

3. 闭包的特性

  • 每个函数都是闭包,函数能够记住自己定义时所处的作用域,函数走到了哪,定义时的作用域就到了哪。
  • 内存泄漏

内存泄漏就是一个对象在你不需要它的时候仍然存在。所以不能滥用闭包。当我们使用完闭包后,应该将引用变量置为null。

function outer(){
    var num = 0;
    return function add(){
        num++;
        console.log(num);
    };
 }
var fun1 = outer();
fun1();              // 1
fun1();              // 2  [没有被释放,一直被占用]
var fun2 = outer();
fun2();              // 1  [重新引用函数时,闭包是新的]
fun2();              // 2

4. 使用场景

任何闭包的使用场景都离不开这两点:

  • 创建私有变量
  • 延长变量的生命周期

一般函数的词法环境在函数返回后就被销毁,但是闭包会保存对创建时所在词法环境的引用,即便创建时所在的执行上下文被销毁,但创建时所在词法环境依然存在,以达到延长变量的生命周期的目的

  • 实现点击第几个button就输出几
<button>1</button>
<button>2</button>

for(var i = 0; i < button.length; i++) {
    (function(item){
        button[item].onclick = function() {
            console.log(item+ 1);
        }
    })(i)
}

  • 柯里化函数
    柯里化的目的在于避免频繁调用具有相同参数函数的同时,又能够轻松的重用
function func(fn, len = fn.length) {
    return _func(fn, len)
}

function _func(fn, len, ...arg) {
    return function (...params) {
        let _arg = [...arg, ...params]
        if (_arg.length >= len) {
            return fn.apply(this, _arg)
        } else {
            return _func.call(this, fn, len, ..._arg)
        }
    }
}

let fn = func(function (a, b, c, d, e) {
    console.log(a + b + c + d + e)
})

fn(1, 2, 3, 4, 5)  
fn(1, 2)(3, 4, 5)
fn(1, 2)(3)(4)(5)
fn(1)(2)(3)(4)(5)

  • 节流防抖
// 节流
function throttle(fn, timeout) {
    let timer = null
    return function (...arg) {
        if(timer) return
        timer = setTimeout(() => {
            fn.apply(this, arg)
            timer = null
        }, timeout)
    }
}

// 防抖
function debounce(fn, timeout){
    let timer = null
    return function(...arg){
        clearTimeout(timer)
        timer = setTimeout(() => {
            fn.apply(this, arg)
        }, timeout)
    }
}

其他
例如计数器、延迟调用、回调等闭包的应用,其核心思想还是创建私有变量和延长变量的生命周期

5. 注意事项

若不是某些特定任务需要使用闭包,在其它函数中创建函数是不明智的,闭包会携带包含其它的函数作用域,因此会比其他函数占用更多的内存。过度使用闭包会导致内存占用过多,所以要谨慎使用闭包。

常问面试题:

let x = 5;
function fn(x) {
    return function(y) {
        console.log(y + (++x));  //14
    }
}
let f = fn(6);
f(7);   
console.log(x); //5
//14
//5

var data = [];
for (var i = 0; i < 3; i++) {
  data[i] = function () {
    console.log(i);
  };
}

data[0](); // 3
data[1](); // 3
data[2]()  // 3
 i 是全局的 i,共用一个作用域,当函数被执行的时候这时的 i=3,导致输出的结构都是3。
 可以用闭包改善上面的写法达到预期效果
 1. 自执行函数和闭包
var data = [];
for (var i = 0; i < 3; i++) {
    (function(j){
      setTimeout( data[j] = function () {
        console.log(j);
      }, 0)
    })(i)
}
data[0]();
data[1]();
data[2]()
2. 使用 let
var data = [];
for (let i = 0; i < 3; i++) {
  data[i] = function () {
    console.log(i);
  };
}
data[0]();
data[1]();
data[2]()
let 具有块级作用域,形成的3个私有作用域都是互不干扰的。

2. 浏览器有哪几种缓存,各种缓存的优先级是什么样的?

在浏览器中,有以下几种常见的缓存:

  • 强制缓存:通过设置 Cache-Control 和 Expires 等响应头实现,可以让浏览器直接从本地缓存中读取资源而不发起请求。
  • 协商缓存:通过设置 Last-Modified 和 ETag 等响应头实现,可以让浏览器发送条件请求,询问服务器是否有更新的资源。如果服务器返回 304 Not Modified 响应,则表示客户端本地缓存仍然有效,可直接使用缓存的资源。
  • Service Worker 缓存:Service Worker 是一种特殊的 JS 脚本,可以拦截网络请求并返回缓存的响应,以实现离线访问和更快的加载速度等功能。
  • Web Storage 缓存:包括 localStorage 和 sessionStorage。localStorage 用于存储用户在网站上的永久性数据,而 sessionStorage 则用于存储用户会话过程中的临时数据。

这些缓存的优先级如下:

  • Service Worker 缓存:由于其可以完全控制网络请求,因此具有最高的优先级,即使是强制缓存也可以被它所覆盖。
  • 强制缓存:如果存在强制缓存,并且缓存没有过期,则直接使用缓存,不需要向服务器发送请求。
  • 协商缓存:如果强制缓存未命中,但协商缓存可用,则会向服务器发送条件请求,询问资源是否更新。如果服务器返回 304 Not Modified 响应,则直接使用缓存。
  • Web Storage 缓存:Web Storage 缓存的优先级最低,只有在网络不可用或者其他缓存都未命中时才会生效。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值