有人能解释一下闭包和匿名函数之间的区别吗?

11

我对Javascript比较新手,了解匿名函数的概念,但是闭包似乎不太清楚。在我的印象里,它们两者之间的相似之处很令人困惑。

有人能否解释一下它们的区别呢?最好附带一些代码片段,以便更清晰地阐述这些要点。


请看这里:https://dev59.com/-nE85IYBdhLWcg3wwWat - Christopher Altman
4个回答

8
重要的区别在于闭包捕获了它定义时所在的作用域。换句话说,闭包可以访问变量及其状态,即使它们属于闭包的父级作用域(例如创建闭包的函数)。这使得闭包可以在程序中捕获和“传输”应用程序状态。而匿名函数则无法做到这一点;它的范围仅限于其主体和签名(即其参数)中定义的变量。编辑:为了澄清:在JavaScript中,这尤其不清楚,因为没有称为闭包的语言构造。你仍然会使用匿名函数来实现。我只是指出了概念上的区别。


2

我在这里解释了这个问题:闭包的禅意

基本上,不涉及技术细节:

  • 匿名函数是一个没有名称的函数(可以分配给变量)。
  • 闭包是一种私有全局变量。

1

匿名函数是指没有名称的函数,除此之外与Javascript中的常规函数相同。 以下是一个例子。 情况1: 这只是一些普通/常规的Javascript函数。

var sayHello = function iWillSayHello(name){
     var fullName = "Hello, " + name; 
     console.log(fullName);
}
sayHello("ABC");    // prints--->  Hello, ABC

案例2: 这是匿名函数, 它与上面的函数具有相同的行为,

var sayHello = function(name){
     var fullName = "Hello, " + name; 
     console.log(fullName);
}
sayHello("ABC");    // prints--->  Hello, ABC

第三种情况: 如果(我认为)你所说的“匿名函数”是指IIFE(立即调用函数表达式), 那么就是这样的,

(function(name){
     var fullName = "Hello, " + name; 
     console.log(fullName);
})();     // prints--->  Hello, ABC

这里的区别在于,在“Case 1”和“Case 2”中,您必须显式调用函数,但是在“Case 3”中,它会自动调用(即使用“()”在末尾调用它声明的函数)。编译器到达该行时将调用它。
另一方面,闭包是一个函数内部的函数。在js中使闭包特殊的是,即使外部函数已返回,它仍然可以访问外部函数的“局部作用域”中的变量值。
闭包=函数+外部上下文
这里有一个简单的例子,
function outerSayHello(firstName){
    var fullName = firstName;
    function innerSayHello(lastName){
         console.log("Hello, ", fullName + " " + lastName);
    }

    return innerSayHello;
}

console.log("1-------------------------");
var sayHello = outerSayHello("A");
sayHello("B");
//Hello,  A B

console.log("2-------------------------");
var sayHello1 = outerSayHello("A1");
sayHello1("B1");
//Hello,  A1 B1

console.log("3-------------------------");
sayHello("b");
//Hello,  A b

console.log("4-------------------------");
sayHello1("b1");
//Hello,  A1 b1

console.log("5-------------------------");
outerSayHello("ABC")("XYZ");
//Hello,  ABC XYZ

to better understand these let's console the sayHello variable

console.log("6-------------------------",sayHello);
/*
  innerSayHello(lastName){
         console.log("Hello, ", fullName + " " + lastName);
    }
*/

这意味着sayHello变量具有指向/引用innerSayHello函数的指针/引用。 由于innerSayHello依赖于fullName变量,在outerSayHello返回后,它仍将保留在堆上,并且fullNameinnerSayHello仍然在堆栈中。 因此,在堆上,将为fullname和innerSayHello创建多个引用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接