深入理解js闭包

136 阅读2分钟

前言:写这篇文章是因为我面试栽在了这个问题上,说起来可笑,我一直觉得自己对这个问题理解的很透彻,其实诶!!!!。闲话不多说,希望大家看完之后有所收获不再栽跟头。。

题目:一句话说明什么是闭包?

说法一:闭包是指有权访问另外函数作用域中的变量的函数。---《js高级程序设计》函数表达式章节的解释。

说法二:闭包是函数和声明该函数的词法环境的组合。这个环境包含了这个闭包创建时所能访问的所有局部变量---《MDN网站的解释》(官方)

说法三:通俗一点讲,就是一个函数里面声明的内部函数,这个内部函数有权访问它外部函数的环境变量。(不够严谨)

闭包的特点:

1、闭包就是能够读取其他函数内部变量的函数,函数没有被释放,整条作用域链上的局部变量都将得到保留


2、用闭包模拟私有方法

引入MDN网站代码的例子说明,代码如下

var makeCounter = function() {
  var privateCounter = 0;
  function changeBy(val) {
    privateCounter += val;
  }
  return {
    increment: function() {
      changeBy(1);
    },
    decrement: function() {
      changeBy(-1);
    },
    value: function() {
      return privateCounter;
    }
  }  
};

var Counter1 = makeCounter();
var Counter2 = makeCounter();
console.log(Counter1.value()); /* logs 0 */
Counter1.increment();
Counter1.increment();
console.log(Counter1.value()); /* logs 2 */
Counter1.decrement();
console.log(Counter1.value()); /* logs 1 */
console.log(Counter2.value()); /* logs 0 */

上述代码中分别两次引用了makeCounter,生成的两个计数器。这两个计数器就是两个闭包,他们具有各自的独立性。每个闭包都是引用自己词法作用域内的变量 privateCounter 。以这种方式使用闭包,提供了许多与面向对象编程相关的好处 —— 特别是数据隐藏和封装。

关于性能方面的考量

如果不是某些特定任务需要使用闭包,在其它函数中创建函数是不明智的,因为闭包在处理速度和内存消耗方面对脚本性能具有负面影响。

例如,在创建新的对象或者类时,方法通常应该关联于对象的原型,而不是定义到对象的构造器中。原因是这将导致每次构造器被调用时,方法都会被重新赋值一次(也就是,每个对象的创建)。