JavaScript知识梳理[四] 作用域和闭包

实际开发中业务逻辑的实现往往都不是只需要简单的几行代码,是会需要封装调用的,此时对作用域和闭包的理解则尤为重要

作用域

 什么是作用域?

 关于作用域我的理解是它是一种规则,规定了变量的可访问范围,域就是范围,作用域就是起作用的范围。

怎么确定作用域?

看定义的变量在哪里起作用,注意变量的作用域在定义的时候已经确定,和调用没有关系,这也就是我们经常听到的词法作用域即静态作用域,和变量对应。

全局变量=》全局作用域即在全局都可以访问;局部变量==》局部的作用域,即在某个函数内可被访问 ==》函数作用域;在ES6 出现了 let const 关键字定义变零 ,此定义的变量具有块级作用域,即只在对应的代码块内起作用。具体的来代码试验看一看

JavaScript知识梳理[四] 作用域和闭包_第1张图片JavaScript知识梳理[四] 作用域和闭包_第2张图片

根据代码对应log 变量的访问权限可以看到,内层作用域可以访问外层作用域的变量,作用域1中打印a 为 undefined 并没有报错,是因为JS 在编译时已经定义了a 在调用是才赋值,所以a没有报错。

作用域链

作用域链的形成,和作用域规则定义有关系,如上变量的可访问范围,内层可以访问外层函数内定义的变量,像这样访问变量时首先从自己当前的作用域查找,如果没有就向父级作用域找,这样一直找到全局作用域,如果还没有就放弃抛出undefined 的异常,这样查找的一个路径过程和作用域可访问的联系形成了作用域链。我理解的作用域链,是一个变量访问查找的路径链。

闭包

什么是闭包?

闭包是一个函数,闭包是一个能够访问其他函数内部变量的函数,那么只有函数内部的子函数才可以读取局部变量,所以闭包可以理解为定义在一个函数内部的函数,本质上 闭包是将函数内部和函数外部连接起来的桥梁。 百度百科定义。

什么时候用闭包?

关于什么时候用闭包,我自己也是迷糊了好久,因为你根据定义是这样的 函数内部可以访问外部函数的变量,这不是由作用域的规则决定的吗,怎么闭包这样还要专门研究呢。其实在不知不觉中我们已经使用了闭包,只是只有在函数内部返回函数时才比较体现出闭包中包含了当前作用域所可访问的变量。

 function createCounter(){
        let count = 0
        const func = function add(){
            return count++
        }
        return func
    }
    let myadd = createCounter()
    const c1 = myadd()
    const c2 = myadd()
    const c3 = myadd()
    console.log(c1,c2,c3)

如上代码就形成了闭包,函数return 函数,那么来捋捋执行顺序,

  1. createCounter 函数部分 在全局上下文中声明了一个 createCounter 的变量,并赋值了一个函数定义;
  2. 在全局执行上下文中声明了一个变量 myadd ;
  3. 调用createCounter 部分将其返回值赋值给 myadd;
  4. createCounter 函数调用时 创建基于当前函数的执行上下文,在当前函数执行上下文中声明一个变量 count 并赋值为0,接下来还声明了变量func ,也赋值了一个函数定义,函数对count 进行了操作并且返回,此时便形成了闭包,作为func 函数定义的一部分,闭包包含作用域中的变量,此处是 count.
  5. 接下来返回func 变量的内容,此时函数的执行上下文结束,count 和 变量 func 不再存在,控制权交给了调用上下文,调用返回func 的内容和包含的闭包,
  6. 调用createCounter() 调用时返回了函数的定义和闭包给到 myadd ,在全局上下文中,
  7. 接下来函数myadd 的调用操作的是 闭包中定义count ,每次操作完count 值会变 console.log 的输出是 0 1 2 

不知道此时对闭包 你还迷糊吗,闭包什么时候用呢,闭包面试的时候会用到 比较多 ,忍不住想笑,因为JS 作用域概念会让闭包无处不在。突出的就是函数返回函数,当一个变量不想暴露出来时 可以使用闭包,比如上例子中的count ,同时还延长了count 变量的生命。

闭包的优缺点

优点:

  1. 闭包中的参数变量不会被垃圾回收机制回收
  2. 闭包中的变量避免了全局的污染
  3. 私有成员的存在,不向外暴露

缺点:

  1. 因为不被垃圾回收机制回收,长期存在内存中,增加了内存的使用量
  2. 闭包使用不当,可能造成内存泄漏,所以建议少用。

你可能感兴趣的:(web,前端)