《JavaScript设计模式与开发实践》之闭包和高阶函数

闭包和高阶函数

  • 函数式语言的鼻祖是 LISP
  • JavaScript在设计之初参考了 LISP两大方言之一的 Scheme,引入了 Lambda表达式、闭包、高阶函数等特性。

闭包

闭包的形成与变量的作用域以及变量的生存周期密切相关。

变量的作用域

  • 变量的作用域,就是指变量的有效范围。
  • 变量的搜索是从内到外而非从外到内的。

变量的生命周期

  • 对于全局变量来说,全局变量的生存周期当然是永久的,除非我们主动销毁这个全局变量。
  • 对于局部变量来说,当退出函数时,它们都会随着函数调用的结束而被销毁。
 var foo = function() {
   var a = 1;
   return function() {
     a++;
     alert(a);
   }
 };

var f = foo();
f(); // 输出:2
f(); // 输出:3
f(); // 输出:4
f(); // 输出:5

变量f 返回了一个匿名函数的引用,它可以访问到 foo()被调用时产生的环境,而局部变量a 一直处在这个环境里。既然局部变量所在的环境还能被外界访问,这个局部变量就有了不被销毁的理由。在这里产生了一个闭包结构,局部变量的生命看起来被延续了。

另一个经典例子,我们通过循环来给每个 div 绑定 onclick 事件,按照索引顺序,点击第 1个 div 时弹出0,点击第 2个 div 时弹出 1,以此类推。

1
2
3
4
5
var nodes = document.getElementsByTagName( 'div' );
for ( var i = 0, len = nodes.length; i < len; i++ ){
      nodes[ i ].onclick = function(){
      alert ( i );
    }
};

把每次循环的 i 值都封闭起来。当在事件函数中顺着作用域链中从内到外查找变量 i 时,会先找到被封闭在闭包环境中的 i

闭包的更多作用

封装变量

闭包可以帮助把一些不需要暴露在全局的变量封装成“私有变量”。

 var mult = function() {
   var a = 2;
   for (var i = 0, l = arguments.length; i < l; i++) {
     a = a * arguments[i];
   }
   return a;
 };
console.log(mult(1, 2, 3)); //输出 12

你可能感兴趣的:(《JavaScript设计模式与开发实践》之闭包和高阶函数)