JavaScript复习——闭包

什么是闭包?

函数嵌套函数,内部函数可以访问外部函数的参数和变量,内部函数在外部函数之外被调用时,就形成了闭包。闭包是一个环境,能读取到其他函数内部的变量。

闭包是一个函数在创建时允许自身函数访问并操作该自身函数之外的变量时所创建的作用域。换句话说,闭包可以让函数访问所有的变量和函数,只要这些变量和函数存在于该函数声明时的作用域内就行。

——《JavaScript忍者秘籍》86

当在函数内部定义了其他函数时,就创建了闭包。闭包有权访问包含函数内部的所有变量。其原理是:在后台执行环境中,闭包的作用域链包含着它自己的作用域、包含函数的作用域和全局作用域。通常,函数的作用域及其所有变量都会在函数执行结束后被销毁。但是,当函数返回了一个闭包时,这个函数的作用域将会一直在内存中保存到闭包不存在为止。

——《JavaScript高级程序设计》p192

.

闭包的优点:

  • 可以在外部读取到函数内部的变量,可以让这些变量的值始终保持在内存中

  • 避免全局变量的污染。定义过多全局变量可能会造成命名冲突,而使用闭包,外层函数的变量或属性,只有通过内部函数访问到,无法通过其他途径访问修改,从而达到了保护变量安全的效果(避免变量污染)。

  • 通过闭包实现了 JavaScript 私有属性和私有方法的效果。若每个模块都可以调用修改变量,当程序越来越复杂之后,会带不可预测的危险。所以推荐变量尽量私有化,当需要让局部变量发挥全局变量的作用时,可以考虑使用闭包。

使用闭包可以在 JavaScript 中模仿块级作用域(JavaScript 本身没有块级作用域的概念),要点如下:创建并立即调用一个函数,这样既可以执行其中的代码,又不会在内存中留下对该函数的引用。结果就是函数内部的所有变量都会被立即销毁——除非将某些变量赋值给了包含作用域(即外部作用域)中的变量。

闭包还可以用于在对象中创建私有变量,相关概念和要点如下。即使 JavaScript 中没有正式的私有对象属性的概念,但可以使用闭包来实现公有方法,而通过公有方法可以访问在包含作用域中定义的变量。有权访问私有变量的公有方法叫做特权方法。可以使用构造函数模式、原型模式来实现自定义类型的特权方法,也可以使用模块方式、增强的模式来实现单例的特权方法。

因为创建闭包必须维护额外的作用域,所以过度使用它们可能会占用大量内存。

由于闭包会携带包含它的函数的作用域,因此会比其他函数占用更多的内存。

——《JavaScript高级程序设计》p192

.

闭包的缺点:

闭包会使函数中的变量一直保存在内存中,不会被浏览器内存回收机制清理,内存消耗大。解决办法是,在退出函数之前,将不需要使用的局部变量删除掉。

一旦数据不再有用,最好通过将其值设置为 null,来释放其引用——这个做法叫做解除引用。适用于大多数全局变量和全局变量的属性。局部变量会在它们离开执行环境时自动被解除引用。解除引用的真正作用是让值脱离执行环境,以便垃圾收集器下次运行时将其回收。

——《JavaScript高级程序设计》p81

你可能感兴趣的:(JavaScript复习——闭包)