资讯专栏INFORMATION COLUMN

到底什么是闭包?深入理解javascript闭包

figofuture / 2274人阅读

摘要:如何使用闭包所以这时候我们就要用闭包去解决这个问题了,先看代码。计数器为这时候的就形成了一个闭包。一个闭包由两部分组成,函数和创建该函数的环境。就是创建了一个匿名函数调用函数解除对匿名函数的引用,以便释放内存

古老定义
闭包(closure),是指函数变量可以保存在函数作用域内,因此看起来是函数将变量“包裹”了起来。
//根据定义,包含变量的函数就是闭包
function foo() {
    var a = 0;
}
cosole.log(a) 
// Uncaught ReferenceError: a is not defined

《JavaScript高级程序设计》对闭包定义

闭包是指有权访问另一个函数作用域中的变量的函数

 //根据《JavaScript高级程序设计》,访问上层函数的作用域的内层函数就是闭包
function foo() {
    var a = 2;
    function bar() {
        console.log(a);
    }
    bar();
}
foo();
《JavaScript权威指南》对闭包定义

函数对象可以通过作用域链相互关联起来,函数体内部变量可以保存在函数作用域内,这就是闭包。

 var global = "global scope"; //全局变量
function checkscope() {
    var scope = "local scope"; //局部变量
    function f() {
        return scope; //在作用域中返回这个值
    };
    return f();
}
checkscope(); // 返回 "local scope"

严格来说,闭包需要满足三个条件:【1】访问所在作用域;【2】函数嵌套;【3】在所在作用域外被调用
  有些人觉得只满足条件1就可以,所以IIFE是闭包;有些人觉得满足条件1和2才可以,所以被嵌套的函数才是闭包;有些人觉得3个条件都满足才可以,所以在作用域以外的地方被调用的函数才是闭包

为什么我们需要闭包

首先来看一个例子,我们来实现一个计数器。

var counter = 0;
function add() {
   return counter += 1;
}
add();
add();
add();// 计数器现在为 3 

现在我们已经达到了目的,可是问题来了,代码中的任何一个函数都可以随意改变counter的值,所以这个计数器并不完美。那我们把counter放在add函数里面不就好了么?

function add() {
    var counter = 0;
    return counter += 1;
} 
add();
add();
add();// 本意是想输出 3, 但输出的都是 1

所以这样做的话,每次调用add函数,counter的值都要被初始化为0,还是达不到我们的目的。

如何使用闭包

所以这时候我们就要用闭包去解决这个问题了,先看代码。

var add = (function () {
    var counter = 0;
    return function () {return counter += 1;}
})();
add();
add();
add();// 计数器为 3

这时候我们完美实现了计数器。这段非常精简,可以拆分成如下等价代码。

function outerFunction () {
     var counter = 0;
     function innerFunction (){
         return counter += 1;
     }
     return innerFunction;
}
var add = outerFunction();
add();
add();
add();// 计数器为 3

这时候的add就形成了一个闭包。一个闭包由两部分组成,函数和创建该函数的环境。环境是由环境中的局部变量组成的。对于闭包add来说,它由函数innerFunction和变量counter组成,所以这时候add是可以访问变量counter的。

使用闭包应注意的问题

由于闭包会携带包含它的函数的作用域,因此会比其他函数占用更多的内存。因此可以手动解除对匿名函数的引用,以便释放内存。

function f2(){
    var n=22;
    var nAdd=function(){n++};
    return function(){
        return {
            n:n,
            nAdd:nAdd
        }
    }
}
//result2就是创建了一个匿名函数
var result2=f2();
//调用函数
console.log(result2());
result2().nAdd();
console.log(result2());
//解除对匿名函数的引用,以便释放内存
result2=null;

1

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/96887.html

相关文章

  • 理解Javascript闭包

    摘要:但是闭包也不是什么复杂到不可理解的东西,简而言之,闭包就是闭包就是函数的局部变量集合,只是这些局部变量在函数返回后会继续存在。可惜的是,并没有提供相关的成员和方法来访问闭包中的局部变量。 (收藏自 技术狂) 前言:还是一篇入门文章。Javascript中有几个非常重要的语言特性——对象、原型继承、闭包。其中闭包 对于那些使用传统静态语言C/C++的程序员来说是一个新的语言特性。本文将...

    dayday_up 评论0 收藏0
  • 深入理解闭包——到底什么闭包

    摘要:古老定义闭包,是指函数变量可以保存在函数作用域内,因此看起来是函数将变量包裹了起来根据定义,包含变量的函数就是闭包定义一闭包是指可以访问其所在作用域的函数按照定义一的说法,需要通过作用域链在全局环境中查找变量的函数就是闭包定义二闭包是指有权 古老定义 闭包(closure),是指函数变量可以保存在函数作用域内,因此看起来是函数将变量包裹了起来 //根据定义,包含变量的函数就是闭包 fu...

    tomorrowwu 评论0 收藏0
  • 不明白JavaScript - 执行环境、作用域、作用域链、闭包吗?

    摘要:所以,全局执行环境的变量对象始终都是作用域链中的最后一个对象。讲到这里,可能你已经对执行环境执行环境对象变量对象作用域作用域链的理解已经他们之间的关系有了一个较清晰的认识。 JavaScript中的执行环境、作用域、作用域链、闭包一直是一个非常有意思的话题,很多博主和大神都分享过相关的文章。这些知识点不仅比较抽象,不易理解,更重要的是与这些知识点相关的问题在面试中高频出现。之前我也看过...

    jlanglang 评论0 收藏0
  • JavaScript深入浅出

    摘要:理解的函数基础要搞好深入浅出原型使用原型模型,虽然这经常被当作缺点提及,但是只要善于运用,其实基于原型的继承模型比传统的类继承还要强大。中文指南基本操作指南二继续熟悉的几对方法,包括,,。商业转载请联系作者获得授权,非商业转载请注明出处。 怎样使用 this 因为本人属于伪前端,因此文中只看懂了 8 成左右,希望能够给大家带来帮助....(据说是阿里的前端妹子写的) this 的值到底...

    blair 评论0 收藏0
  • 深入浅出Javascript闭包

    摘要:如果有时需要得到函数内的局部变量。上面代码中,函数就在函数内部,这时内部的所有局部变量,对都是可见的。所谓内存泄漏指任何对象在您不再拥有或需要它之后仍然存在。闭包不能滥用,否则会导致内存泄露,影响网页的性能。 一、引子 闭包(closure)是 Javascript 语言的一个难点,面试时常被问及,也是它的特色,很多高级应用都要依靠闭包实现。本文尽可能用简单易懂的话,讲清楚闭包的概念、...

    tyheist 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<