js忍者秘籍读书笔记(前五章)闭包

这一章的目标是:理解闭包、掌握闭包的工作原理

闭包的好处:

  1. 可以实现JavaScript没有的私有变量
  2. 可以通过减少代码数量和复杂度来添加高级特性

什么是闭包呢?(自己的理解)
内部函数调用外部函数的变量可以形成闭包

理解闭包

 允许函数访问并操作函数外部的变量
var globe_name = ''
function fn() {
     var name = 'tom'
     function fn_name() {
         return name
     }
     globe_name = fn_name()
 }
 fn()
 console.log(globe_name);// tom

以上代码就是一个闭包

按理说,fn方法执行完之后,这个作用域应该消失,不会再获取到内部的变量,但是现在执行内部函数时候内部变量仍然存在

当在外部函数中申明内部函数时,不仅仅定义 函数的声明,而且还创建了一个闭包。改闭包不仅包含了函数的声明,还包含了函数声明时该作用域中所有的变量。当最终执行内部函数是,尽管声明时的作用域已经消失了,但是通过闭包,仍然能访问到原始作用域

谨记
每一个通过闭包访问变量的函数都具有一个作用域链,作用域链包含闭包的全部信息

虽然表报是非常有用的,但是不能过度使用。使用闭包时,所有的信息都会存储在内存中,知道JavaScript引擎确保这些信息不再使用(可以安全的进行垃圾回收)或页面卸载时,才会清理这些信息

闭包的使用

JavaScript没有私有变量,但是闭包可以实现一个类似于其他语言的私有变量

function Obj(num1) {
   let num = num1 // 闭包模拟私有变量
   this.getNum = function () {
       return num
   }
   this.addNum = function () {
       num++
   }
}

let a = new Obj(2)
a.addNum()

上面的例子,其中可以通过getNum方法可以获取私有变量num的值,但是不能直接访问num这个私有变量。并且不能修改,有效的阻止了对变量不可控的修改
在外部是不能直接访问num的

回调函数中使用闭包

下面代码实现一个动画

let box1 = document.getElementById('box1')
let box2 = document.getElementById('box2')
function animation(ele) {
    let ticket = 0
    let timer = 0
    timer = setInterval(function () {
        if (ticket < 100) {
            ticket++
            ele.style.width = `${ticket}px`
        } else {
            clearInterval(timer)
        }
    }, 100)

}
animation(box1)
animation(box2)

假设,这个动画没有使用闭包来完成,则里面使用的变量ele(DOM元素的引用)、ticket(计数器)、timer(计时器)都得是全局变量,这样一个元素使用动画的时候没有问题,但是如果是多个的话,就会出问题,变量会发生冲突。
所以使用闭包,就会使得每个动画都能够有自己的作用域链中的私有变量,不会互相影响

使用闭包的理由
一次性同时做许多事情,例如事件绑定、动画甚至是服务端请求都会变得非常困难

这里这个动画例子让我想起来在刚学习js的时候写了一个轮播图,当时是写了一个全局的方法,也需要使用计数器和定时器,但是页面会有多个地方需要使用轮播图,所以写了公共的方法。然后在执行的时候发现页面轮播图效果没有按照预期效果执行,计数器的累加错误导致不同地方的轮播图没有按照顺序显示,后来就改成了构造函数来实现,这样计数器就没有再被互相影响,当时只知道这么写管用,但是不知道原因,现在理解了。

当时出现问题的原因就是因为执行元素没有属于自己的私有变量,导致被互相影响

通过执行上下文来跟踪代码

前面讲过JavaScript有两种代码类型:一种是全局函数、一种是函数代码

既然有两种类型的代码,name就有两种执行上下文:全局执行上下文和函数执行上下文

二者差别是:
全局执行上下文只有一个,当JavaScript程序开始执行时就有奖创建了全局上下文;而函数执行上下文是在每次调用函数时,就会创建一个新的

执行上下文也称为调用栈

你可能感兴趣的:(闭包,js基础,忍者秘籍,javascript)