8000 重新认识闭包 · Issue #13 · tiger5wang/blog · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

重新认识闭包 #13

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
tiger5wang opened this issue Nov 8, 2019 · 0 comments
Open

重新认识闭包 #13

tiger5wang opened this issue Nov 8, 2019 · 0 comments

Comments

@tiger5wang
Copy link
Owner

说起闭包,一般是 两个问题:

  1. 什么是闭包;
  2. 闭包的作用是什么;

首先说一下什么是闭包

(function() {
    let local = '变量';
    function foo(){
        console.log(local)
    }
})()

这段代码中,自执行函数中,有一个局部变量 local, 有一个函数 foo , foo 函数可以访问到其所在作用域的变量 local,这就形成了一个闭包
下面是 MDN 对闭包的定义

函数与对其状态即词法环境(lexical environment)的引用共同构成闭包(closure)

也就是说 闭包可以从函数内部访问到外部函数的作用域,注意这个作用域不是所有的外部作用域,而是函数所在的词法作用域

通常情况下,我们说闭包最多的是这样的:
函数嵌套函数,然后 return 一个函数
比如这样:

function foo(){
  var local = 1
  function bar(){
    local++
    return local
  }
  return bar
}
var func = foo()
func()

这里面确实有闭包,local 变量和 bar 函数就组成了一个闭包。

但是为什么需要函数嵌套函数呢,为什么要 return 一个函数呢?

函数嵌套函数,是要产生一个局部作用域(这里就是外层函数的函数作用域),在这个作用域内,函数 bar 引用了bar 函数外部的其所在词法作用域内的变量 local;函数 bar 对其外部作用域的引用 就构成了 闭包。而return bar 是为了使用这个闭包,把 return bar 改为 window.bar = bar 也是一样的,只要让外部能访问到这个 bar 函数就可以了,这使得这个函数在定义时的词法作用域以外的地方被调用。所以说 闭包使得函数可以继续访问定义时的 词法作用域。

当然,无论使用何种方式对函数类型的值进行传递,当函数在别处被调用时都可以观察到 闭包。

        function foo() {
            let a= 11;
            function bar() {
                console.log(a)  //11
            }
            baz(bar)
        }
        function baz(fn) {
            fn()  // 这就是闭包
        }

将内部函数 bar 传递给外部函数 baz , 当调用这个内部函数 fn 时,它涵盖foo作用域的闭包就体现出来了,因为它可以访问到 到 foo 作用域内部的变量 a.
当然,传递函数当然也可以是间接的:

        let fn;
        function foo() {
            let a= 11;
            function bar() {
                console.log(a)  //11
            }
            fn = bar;
        }
        foo();
        fn() // 这就是闭包

说明了 无论通过何种方式将 内部函数 传递到所在作用域以外,它都会持有原始定义的作用域的引用,无论在何处执行这个函数都将使用闭包。

闭包的作用

闭包常常用来 【间接访问一个变量】,换句话说就是:【隐藏一个变量】或者【封装变量,收敛权限】
比如验证一个用户是否是第一次登录

function isFirstLoad() {
    var _list = []
    return function(id) {
        <!--_list 为自由变量-->
        if(_list.indexOf(id) >= 0) {
            return false
        } else {
            _list.push(id)
            return true
        }
    }
}
var firstLoad = isFirstLoad()
firstLoad(10)  // true
firstLoad(10)  //false
firstLoad(20)  //true
firstLoad(20)  // false
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant
0