likes
comments
collection
share

5分钟了解闭包的概念

作者站长头像
站长
· 阅读数 18

目的:了解闭包

阅读时长: 5 分钟

来源: 整理自慕课网教程

自说自话: 我刚学前端那会儿,一直不了解闭包是什么,如今了解了一些,就来自己尝试输出一下。

张三丰教张无忌太极拳的一段剧情:

张三丰: “还记得吗?”

张无忌: “全都记得。”

张三丰: “现在呢?”

张三丰: “啊,已经忘了一大半。”

张三丰: “不坏不坏,忘得真快,那么现在呢?”

张无忌: “已经全都忘了,忘得干干净净。”


1. 从现在开始,忘了什么是闭包,因为闭包本来就是一个抽象的概念,我们只去了解它的使用场景和作用

javascript中有个作用域的概念。

  1. 全局作用域
  2. 函数作用域

5分钟了解闭包的概念

关于作用域,你必须要知道的是: 作用域取决于函数定义的地方,与函数执行无关。

这句话怎么理解? 看一段代码:

看一段代码



function F1() {


    var a = 100;
    return function () {
        console.log(a)
    }
}
var f1 = F1();
var a = 200;
f1()

这段代码打印结果: 100; 我们这样来看,

F1定义的时候,作用域已经生成。

5分钟了解闭包的概念

然后,把F1 赋值给 f1, 此时,f1 是一段函数,如下:

function() {
    console.log(a)
}

然后,定义了一个全局变量a,在全局环境去执行f1.

注意: 作用域取决于函数定义的地方,与函数执行无关。

此时f1执行,去找a的变量,F1的局部作用域去找。

他会找到a = 100; 而不是a=200;

2. 了解了作用域,来看看闭包的使用场景

  1. 函数作为参数传递
  2. 函数作为返回值

还是刚刚的例子

function F1 () {
    var a = 100;
    return function () {
        console.log(a)
    }
}
var f1 = F1();
function F2(fn) {
    var a = 200;
    fn();
}
F2(f1)
// 100

由上面的例子能看到,闭包的作用是: 封装变量, 收敛权限

看一个实际的应用场景:

function isFirstLoad() {
    var _list = [];
    return function (id) {
        if (_list.indexOf(id) >= 0) {
            return false;
        }else {
            _list.push(id)
            return true
        }
    }
}
var firstLoad = isFirstLoad()
firstLoad(1) // true
firstLoad(2) // true
firstLoad(1) // false

这里在isFirstLoad 里面定义了一个数组, return了一个判断是否重复的函数。

然后在全局作用域中去调用该方法,这样的好处是: 无论如何操作,都不会污染isFirstLoad()方法中的_lsit数据了。

最后在看一个生成10个a,点击每个a,打印出对应下标的例子

var a, i;
for(var i = 0; i < 10; i++ ){
    a = document.createElement('a')
    a.innerHTML = i + '<br>'
    a.addEventListener('click', function(e) {
        e.preventDefault()
        alert(i)})
    document.body.appendChild(a)
}

这是一个错误的写法,点击每个按钮都是10,这个原因是什么呢?

  1. i 定义在全局作用域
  2. 循环创建10个a标签,这时候,标签创建完毕,i也循环完毕。此时i = 10;
  3. 点击a标签,i 去 全局作用域查找,所以,无论点哪一个a,都会alert10.

修改代码:

var a, i;
for(var i = 0; i < 10; i++ ){
    (function(i) {
        a = document.createElement('a')
        a.innerHTML = i + '<br>'
        a.addEventListener('click', function(e) {
        e.preventDefault()
        alert(i)})
        document.body.appendChild(a)
    })(i)
}
  1. 每次循环的时候,生成一个新的自执行函数,把i 传递进去,这样每个函数都有自己的作用域。
  2. 点击a的时候,去自己的作用域查找,不查找全局作用域,问题得到解决。

如有不妥之处,望指出。

谢谢阅读!

我是海明月,前端小学生。

转载自:https://juejin.cn/post/6844903831747166222
评论
请登录