美文网首页饥人谷技术博客@产品程序员
三分钟看完JavaScript作用域与闭包

三分钟看完JavaScript作用域与闭包

作者: clancysong | 来源:发表于2018-02-24 21:57 被阅读39次
    image
    • 写了挺久的也没写多少。
    • 所以说其实闭包是很简单的啊233。

    正文

    作用域

    什么是作用域

    作用域按词义理解可以理解为变量的作用范围,也就是在哪里才能够访问到这个变量。

    function foo() {
        function bar() {
            var b = 2
        }
        console.log(b)  // b is not defined
    }
    

    以上代码中,函数foo就创建了一个作用域,foo内部的函数bar也创建了一个作用域。这时如果在foo内访问bar内的变量b,则会报错:b未被定义。这是因为bar的作用域确定了变量b只在bar的函数体内可以被访问。

    function foo() {
        var a = 1
        function bar() {
            console.log(a)  // 1
        }
    }
    

    而如果在foo内定义变量a并在bar内调用的话则会正常访问并输出。这是因为foo和bar形成了嵌套的关系,而在作用域中查找变量时会首先从自身作用域开始寻找,如果没有找到则会继续跳转到父级作用域中继续查找,直到得到该变量或查找到全局作用域为止。而这种作用域层层嵌套的结构就被称为作用域链。

    函数作用域和块级作用域

    在ES6出现之前,JavaScript中没有块级作用域的概念,只有函数才能创建作用域,也就是函数作用域。

    函数作用域如上文所示,只要创建了一个函数就会创建一个函数作用域,外界无法访问作用域内部的变量。而块级作用域则由一对花括号创建:

    var foo = true
    
    if (foo) {
        var a = 10
    }
    
    console.log(a)  // 10
    

    以上代码看似为a创建了一个单独的作用域,然而因为JavaScript中没有块级作用域,导致在花括号外依然能够访问到a。这很令人困惑,而且可能会导致一些意想不到的问题。好在ES6解决了这个问题,使用let关键字来声明变量,就可以将变量绑定到块级作用域中。

    var foo = true
    
    if (foo) {
        let a = 10
    }
    
    console.log(a)  // a is not defined
    

    词法作用域和动态作用域

    简单来说,词法作用域取决于代码书写的位置,而动态作用域取决于代码运行的位置。JavaScript中采用的是词法作用域,记住这一点对理解闭包很有帮助。

    闭包

    什么是闭包?

    var a = 10
    function foo() {
        console.log('a')  // 10
    }
    

    这就是一个闭包。

    当然这样是难以理解的,这里将它稍微修改一下:

    function foo() {
        var a = 10
        function bar() {
            console.log(a)
        }
        return bar
    }
    
    var a = 20
    var baz = foo()
    baz()   // 10
    

    首先按照错误的思路来理解这段代码:foo执行时声明一个函数bar并返回,这里将它赋值到变量baz上。foo执行结束后其内部作用域理应被销毁。这时再执行函数baz时需要访问变量a,于是就在当前作用域中找到a为20并输出。

    然而实际上foo函数在执行结束后,由于bar函数内部存在对foo内变量a的引用,使得foo的内部作用域不会被销毁而是随着函数bar一同被保留了下来。当bar函数在外部被调用时,访问的也并非是它被调用时所在的作用域,而是它被定义时所在的作用域,也就是词法作用域

    回到这部分第一句话,什么时候会产生闭包?

    当一个函数拥有其自身作用域以外的变量的引用,这时就产生了闭包。

    闭包基于词法作用域产生,只要掌握了作用域,也就理解了闭包。而实际编程中闭包也总是在不经意间被创建,我们只需要看到写完的代码,能知道 “啊,这是闭包” 就够了。

    结语

    推荐《你不知道的JavaScript(上卷)》

    相关文章

      网友评论

        本文标题:三分钟看完JavaScript作用域与闭包

        本文链接:https://www.haomeiwen.com/subject/ihrcxftx.html