闭包其实很简单

作者: MountainKing | 来源:发表于2015-12-22 23:05 被阅读344次

什么是闭包

闭包是函数式编程基石,在形式上就是一个函数内部定义另一个函数,函数的堆栈在在函数返回后并不释放,我们也可以理解为这些函数堆栈并不在栈上分配而是在堆上分配。

看完概念是不是一头雾水?没关系,我一向不喜欢在概念上理解技术,直接看闭包能解决什么问题。本文采用JS代码辅助理解,虽然JS是一门设计糟糕、备受吐槽的语言,但是JS的闭包特性是90年代以后所有语言里最好的。

用途

  1. 访问权限控制

面向对象语言如Java、C++都会有private、public关键字,不允许从类外部直接访问特定成员变量,需要通过成员函数来访问,这是一个很普遍、很合理的需求。
先复习一下JS的变量作用域。
函数内部可以访问全局变量:

var n=1;
function print(){
     console.log(n);
};
print(); // 1

但是从函数外部不能访问函数内部变量:

function fun() {
     var a = 0; 
};
console.log(a); // error

于是闭包派上用场了:

function outer() {
     var n = 2;
     function inner() {
       return n; 
     };
     return inner();
}
var result = outer();
console.log(result); // 2
  1. 延长变量生命周期

在面向对象语言里,函数内的变量都是在栈上分配的,函数调用完成后,栈销毁,变量的生命周期结束。而对象是在堆分配的,会常驻内存,除非被手动或自动回收掉。
闭包再次救场:

function createCounter() {
     var counter = 0;
     function increment() {
       counter = counter + 1;
       console.log("Number of events: " + counter);
     }
     return increment;
}
var incr = createCounter();
incr(); // 1
incr(); // 2
incr(); // 3

函数式编程

近几年,老古董函数式编程大有卷土重来、取代面向对象的趋势,我一向认为一门新技术要证明自己牛逼,最好的策略不是去炫技,因为很多看客好奇心不强、学习能力一般,很容易就被吓跑了。毕竟技术是来解决问题的,下面我分别用Java和JS实现一个能自增自减的程序,看看两者有啥区别。
Java:

public class Counter {

    private int counter;
    
    public Counter() {
        counter = 0;
    }
    
    public int getCounter() {
        return counter;
    }
    
    public void incr() {
        ++counter;
    }
    
    public void decr() {
        --counter;
    }
    
    public static void main(String[] args) {
        Counter counter = new Counter();
        counter.incr();
        counter.incr();
        counter.decr();
        System.out.println(counter.getCounter()); // 1
    }
}

JS:

function Counter() {
  var counter = 0;
  function incr() {
    ++counter; 
  }
  function decr() {
    --counter; 
  }
  function getCounter() {
    return counter; 
  }
  return {
    incr: incr,
    decr: decr,
    getCounter: getCounter
  }
}
var counter = Counter();
counter.incr();
counter.incr();
counter.decr();
console.log(counter.getCounter()); // 1

剥离函数式编程天生的骄傲,排除外界的干扰,还原它的本质。至于面向函数和面向对象哪个好,不是三言两语能说清楚的,待我日后再更。

相关文章

  • 闭包其实很简单

    什么是闭包 闭包是函数式编程基石,在形式上就是一个函数内部定义另一个函数,函数的堆栈在在函数返回后并不释放,我们也...

  • 2019-01-07

    闭包 什么叫闭包?闭包的定义其实很简单:函数 A 内部有一个函数 B,函数 B 可以访问到函数 A 中的变量,那么...

  • JS_闭包其实很简单

    JS_闭包其实很简单 闭包其实就是一个函数,执行以后,接受里面返回的函数,然后保存到一个全局变量中。要理解闭包,首...

  • JavaScript 闭包

    本篇文章包懂 什么是闭包 总有人看到闭包就头疼,因为“闭包”二字实在让人搞不懂它的语义。但闭包其实是个很简单的概念...

  • js 中的闭包

    什么是闭包? 闭包的定义其实很简单:函数 A 内部有一个函数 B,函数 B 可以访问到函数 A 中的变量,那么函数...

  • 闭包的使用场景,使用闭包需要注意什么

    闭包 什么是闭包 闭包很简单,就是能够访问另一个函数作用域变量的函数,更简单的说,闭包就是函数,只不过是声明在其它...

  • 前端面试题【Day01】

    本篇绪论1,闭包2,深浅拷贝3,防抖、节流 1,闭包 闭包的定义很简单:函数 A 返回了一个函数 B,并且函数 B...

  • Swift入门基础5——闭包

    何为闭包? Swift中的闭包和OC中的block很相似(其实也有其他语言有闭包的概念)。所谓闭包,就是可以捕获其...

  • Js-闭包

    「闭包」 要理解什么闭包,首先要知道闭包为啥出现,实际代码中,我们想在某一的作用域中使用一个变量,很简单,直接在外...

  • 闭包歧义

    // 闭包歧义 // 完整的闭包是将闭包的输入和输出都写上,然后用 in 隔离 参数和实现 // Void 其实是...

网友评论

    本文标题:闭包其实很简单

    本文链接:https://www.haomeiwen.com/subject/mpaphttx.html