JavaScript里的闭包是什么,应用场景有哪些
很多开发语言中用到了闭包,如JavaScript、Python、Ruby、Java(java 8及以上版本),也许大家曾挣扎着去理解闭包这个苦涩难懂的概念,接下来本文就以JavaScript语言为例以通俗易懂的方式来讲解闭包的概念,以及闭包的应用场景。
工具/原料
JavaScript
一、准备工作
1、在正式介绍闭包前,我们先引入一个概念,即高阶函数。如果一个函数A的实参为函数,或者函数A内部又定义了函数B,则称A为高阶函数。其中B可称为内层函数,这时A相对于B来说又可称为外层函数。下图中highLevelFunct1接收了函数作为参数,highLevelFunct2中定义了内层函数,所以他们都称为高阶函数。
2、内层函数可以访问外层函数的局部变量,如下图所示,内层函数size可以直接访问外层函数highLevelFunct2的局部变量arr。
3、我们先不用去理会闭包的官方定义(从字面上很难看懂),只需要有这样的概念,即闭包实质上就是一个函数,只不过这个函数有些“特异功能”。接下来在栏目二中我们通过举例具体讲解闭包的“特异功能”。
二、举例讲解
1、1.通过闭包可以让内层函数延迟执行,只有需要时再执行它function highLevelFunct2() { var arr = ['a', 'b', 'c']; var size = function () { alert(arr.length); }; return size;}function testClosure() { var f = highLevelFunct2(); f();}f为函数变量,保存了内层函数size及size对应上下文环境(本例的上下文环境为变量arr)。下图中118行,调用highLevelFunct2时,其中的内层函数size并没有立即执行。当我们需要执行它时(第119行)才会真正执行,得到arr的长度为3。
2、通过闭包,内层函数可以将外层函数的局部变量进行封装,封间糈尢各闭后就只有内层函数才能访问到外层函数的局部变量。比如我们要实现一个计数器,可以写如下代码:functi泠贾高框on myCounter() { var counter = 0; return function add () { return counter += 1; }}函数myCounter内部定义了一个计数器变量counter,内层函数add实现了对计数器的+1操作。我们紧接着定以下调用函数:function testClosure() { var increase = myCounter(); increase(); increase(); increase();}通过testClosure函数,我们获得了计数器,并通过increase()函数实现+1操作。
3、注意:使用闭包时,返回函数中的变量一般不用循环变量或者后续值会变更的变量。假如有如下函数:function count(像粜杵泳) { var arr = []; for (var i = 0; i <= 2; i++) { arr.push(function () { return i; }); } return arr;}此函数返回了一个长度为2的函数数组。接着执行以下调用函数:function testClosure() { var results = count(); var func1 = results[0]; var func2 = results[1]; var func3 = results[2];}你可能会认为返回结果分别为0、1、2,可意外的是,输出的结果是3、3、3.这是由于内层函数不是立即执行函数,当for循环结束时i已经变为了3,所以生成的三个内层函数返回值全是3.