前端学习/踩坑系列3:讲一下闭包

299 阅读2分钟

首先JavaScript并不像其他面向对象语言一样,有很明显的面向对象的特征。可以说JavaScript既有面向对象的特征,也有面向过程的函数式语言的特征。所以会更加灵活,更加难学。

JavaScript的面向对象是通过原型链和闭包实现的,而闭包是调用私有属性的接口,是为了解决一个对象函数可以拥有私有属性,并且外部可以通过闭包访问私有变量。同时闭包也是一种保护私有属性的机制,该属性只能通过其所属的函数提供的方法才能改变,里面的私有属性不受外界干扰。

实现闭包的简单例子:

function outerFn(){
  var count = 0;
  function innerFn(){
    return count += 2;
  }
  return innerFn; // 返回的是Function,而这个Function返回的是count
}

var add = outerFn(); // 这里对外部函数进行了初始化,给count赋初始值

add(); // 2
add(); // 4

首先是定义一个函数,这个函数存在一个内部函数是操作其私有属性的,如上例的count,该属性的作用域只有outerFn(),即变量函数私有。又innerFn()同样可以操作count,而outerFn()暴露出了innerFn(),即提供了外部访问count的接口

而在把outerFn()赋值给add变量的时候,之所以需要先执行一次,是要进行变量的初始化,会创建一个变量count,而这个变量被innerFn()引用着,而innerFn()又赋值给了add,故无法被释放,每次调用add,相当于调用了innerFn(),而count就会被操作,同时返回操作后变量的值。

由于count是私有的,而且只能通过innerFn()操作,故保护了私有变量。

闭包的其他使用:

//使用匿名函数
var add = (function(){
  var count = 0;
  function innerFn(){
    return count += 2;
  }
  return innerFn; // 返回的是Function,而这个Function返回的是count
})();

add(); // 2
add(); // 4

// 使用构造函数:会更加像面向对象的方式
function outerFn(){
  var count = 0;
  this.innerFn = function(){
    return count += 2;
  }
}

var a = new outerFn();
a.count  //undefined
a.add(); //2
a.add(); //4


小声说话:渺沧海之一粟,哀吾生之须臾。——苏轼《前赤壁赋》