javascript 函数中的匿名函数一定是闭包吗?

如题所述

“函数是不是闭包” 这种问题本身是不对的。虽然在网络上常见这种提法,但是其实是因为对 Javascript 实现机制不清楚胡乱猜测导致的误解。


首先,一个函数不管是不是匿名函数,和闭包之间根本没有任何关系!

所谓闭包究竟是什么?网络上说法云里雾里,讲得高深莫测,但是其实只要稍微有一些编译器实现机制的认识,就会知道闭包其实是非常简单的东西。

我们先来看看下面的代码:

function funcA() {
    var a = 1, b = 2;
    return funcB();
    
    function funcB() {
        // 注意,a 和 b 在本函数里根本没有定义,但是竟然能访问到
        return a + b;
    }
}

var a = funcA();
// a 将会等于 3

上面的代码神奇的地方有几点:

1、函数可以嵌套定义(而 C/C++ 就不行)

2、嵌套的函数可以访问到它的上级函数的局部变量


先说嵌套,其实这个能力没什么神奇的,C/C++ 编译器稍作修改就能支持,但是这么实现出来,虽然函数可以嵌套了,实用价值还是比较小,因为访问不到上级函数的局部变量啊。而且我们知道 Javascript 的嵌套函数是可以层层嵌套的,而访问时最内层的函数也能够访问到最顶层的函数的变量,非常有用!


说到这里,和闭包有什么关系呢?


闭包,就是用来实现这种嵌套时还能够层层向上访问变量的功能的!对的,它就是一个简单的编译器技巧,用来使得内部函数能够访问上级函数的变量。


简单来说,它具体实现的方法为,在每个函数上附加上一个额外的隐藏对象,这个对象其实就叫做闭包对象,你别管他名字怎么叫,它就是个普通的对象!它没什么神奇的,就是记录了本函数内部的变量列表而已。而且这个闭包对象还保存了一个指向上级函数的闭包对象的引用。


这样一来,就形成了一个链条。当我们在一个函数里访问一个变量的时候,编译器会先看看在本闭包里到底有没有这个变量,如果没有就向上寻找。如果找到,那就用,如果一直找到头也没有,那就提示出错。


明白了吗?就是这么回事。但是最后还有一点,按照上面的方式构造出来的闭包好像是固定的,其实每次调用一个函数的时候,都会单独创建一个新的闭包对象和这一次调用对应起来。因此其实闭包链是动态创建的。


其实要说清楚这个问题,得配几个图。但是时间所限,我就不细说了。如果你能理解那最好,如果还是有疑问,那你以后慢慢接触得多了就知道了。


最后解释一下这段代码,加深理解

function X() {
    return function() {
        // ...
    }
}


注意X里面这里返回了一个匿名函数。一定要记住这个函数由于是嵌套定义在 X 里的,因此它的闭包对象是链接到 X 的闭包对象上的,所以在这个匿名函数里是可以访问到 X 内部的变量的。其实就是这么简单。不管你嵌套多少层,匿名还是有名。我只看你定义时的嵌套关系,就知道闭包链的整个链条!其他就顺理成章了。


最后推荐两个让你走出国内普遍存在的误区的方法,一是多看 ECMA-262, 5e,这里面包含了所有标准化的 Javascript 的算法实现细节。另外一个是研究 Google 的 v8 引擎。自己下代码下来编译调试下,很多问题就能搞清楚了。


就说这么多了。

温馨提示:内容为网友见解,仅供参考
第1个回答  2013-08-27
不一定是,只有将那个内部的匿名函数返回才算是,如果不返回并不是一个闭包

javascript什么是匿名函数和闭包?
综上所述,匿名函数与闭包在JavaScript中扮演重要角色,它们为开发者提供灵活的函数定义和执行方式。通过IIFE,可以模拟块级作用域,解决变量作用域问题,实现更精细的控制与逻辑处理。

搞明白JavaScript中的匿名函数
JavaScript中没有块级作用域,变量会随作用域的结束而销毁。通过匿名函数可以模拟块级作用域。实现步骤如下:1. 通过匿名函数创建闭包。闭包允许访问函数作用域内的变量,并在函数外部使用。闭包的创建往往依赖于匿名函数。2. 模拟块级作用域,减少全局变量的使用。执行完毕后,相关变量被销毁,节省内存。...

javascript闭包是什么?
定义在函数内部的,能访问外部函数的变量的函数叫做闭包。所以闭包是相对的。就像你上面:function(){return "我的父亲(getNameFunc)不是闭包,我才是闭包,这是为什么呢?";};这个匿名函数是定义在getNameFunc方法内的,能访问getNameFunc中的属性,所以他才是闭包。

javascript中的匿名函数和function有什么区别
匿名函数,用于闭包 function 用于定义函数或对象

闭包的理解
闭包就是能够读取其他函数内部变量的函数。例如在javascript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数“。在本质上,闭包是将函数内部和函数外部连接起来的桥梁。闭包是个精确但又很难解释的电脑名词。在Perl里面,闭包是以匿名函数的形式来实现,具有持续参照...

javascript中:(function(){})();如何理解?
不会影响到其他代码。在前端开发中,这是一种非常常见且实用的技术。总结来说,`{});` 是JavaScript中一种特殊的语法,用于定义并立即执行一个匿名函数表达式。这种写法在前端开发中有着广泛的应用,对于理解JavaScript的作用域、闭包等概念有着重要的作用。

javascript中: (function(){})();如何理解?
javascript中: (function(){})()是匿名函数,主要利用函数内的变量作用域,避免产生全局变量,影响整体页面环境,增加代码的兼容性。(function(){})是一个标准的函数定义,但是没有复制给任何变量。所以是没有名字的函数,叫匿名函数。没有名字就无法像普通函数那样随时随地调用了,所以在他定义完成后就...

浅谈js中什么是封闭函数、闭包、内置对象
1、一般函数的定义和执行函数2、封闭函数的定义和执行:(function(){...})();还可以在函数定义前加上"~"或者"!"符号来定义匿名函数。三、闭包闭包就是函数嵌套函数,内部函数可以引用外部函数的参数和变量,参数和变量不会被垃圾回收机制收回 1、闭包用途1:将一个变量长期驻扎在内存当中,可用于...

javascript中: (function(){})();如何理解?
匿名函数有多种应用场景,例如作为事件处理程序,创建闭包等。与函数声明`function setFn() { ... }`不同,函数表达式`var setFn = function() { ... }`虽然也定义了函数,但这里函数是赋值给一个变量的,使其具有名称。而直接使用`function() { ... }`的方式就是典型的匿名函数表达式。总...

JavaScript 里的闭包是什么?应用场景有哪些
一、闭包 1、createFunction()创建时,它(compare)的作用域包含createFunction()函数的活动对象和全局对象。\/\/创建函数var compare = createFunction("name");console.log(typeofcompare); \/\/function2、匿名函数被执行时,创建自己的活动对象和可以访问createFunction()的执行环境。\/\/调用函数var result...

相似回答