Javascript闭包

Javascript闭包,javascript,closures,Javascript,Closures,我仍然对JavaScript中的闭包概念感到困惑。我得到的结论是,闭包是内部函数在母函数返回后访问在其母函数中创建的变量的能力。 但是我仍然很困惑,如果我们可以在函数内部创建一个变量,为什么我们必须创建内部函数来保护局部变量?您需要创建具有作用域变量的内部函数的原因是面向对象的封装。它本质上是私有变量 变量是“闭合的” 请看return语句。它返回公共接口—一些方法可以访问私有变量,因为它们位于内部函数中。它使用JavaScripts函数作用域变量来创建面向对象的封装 之后,我可以这样做: va

我仍然对JavaScript中的闭包概念感到困惑。我得到的结论是,闭包是内部函数在母函数返回后访问在其母函数中创建的变量的能力。
但是我仍然很困惑,如果我们可以在函数内部创建一个变量,为什么我们必须创建内部函数来保护局部变量?

您需要创建具有作用域变量的内部函数的原因是面向对象的封装。它本质上是私有变量

变量是“闭合的”

请看return语句。它返回公共接口—一些方法可以访问私有变量,因为它们位于内部函数中。它使用JavaScripts函数作用域变量来创建面向对象的封装

之后,我可以这样做:

var obj = myObject('Hello World');
obj.increment();
obj.increment();
console.log(obj.getValue());
console.log(obj.getMessage);
// should be undefined
console.log(obj.value);
注意:此时,使用者无法访问受保护/封装的值或消息

现在,这里是kicker-对象是可变的,因此调用方可以添加方法,甚至替换方法。因此,您可能会认为有人可以添加一个公开内部的方法。但是,由于函数的作用域(闭包-它们被关闭了),它们不能这样做。只有嵌套函数可以访问外部函数的变量。因此,如果调用者添加了一个方法来返回内部消息,那么他们将无法获得访问权,并且该消息将是未定义的

上述代码输出:

2
Hello World
undefined
作为补充说明,我正在使用

下面是一篇关于使用闭包的模块模式的好博文:


关键是变量在两个函数之间共享。如果您在内部函数中声明了变量,那么外部函数将无法访问它,因此它不会被共享。

您刚刚回答了问题,内部函数会保护它的变量

闭包允许您将某些数据(环境)与对该数据进行操作的函数相关联。这与面向对象编程有明显的相似之处,在面向对象编程中,对象允许我们将一些数据(对象的属性)与一个或多个方法相关联

when not to use
如果特定任务不需要闭包,那么在其他函数中不必要地创建函数是不明智的,因为它会在处理速度和内存消耗方面对脚本性能产生负面影响


例如,在创建新对象/类时,方法通常应该与对象的原型关联,而不是定义到对象构造函数中。原因是,每当调用构造函数时,方法都会被重新分配(即,对于每次对象创建)。

如果在内部函数中声明变量,则每次调用内部函数都会创建一个新变量:以前调用所做的任何修改都将丢失


但是,如果变量在外部函数中声明,那么对内部函数的多个调用将看到同一个变量,一个调用将看到前一个调用的修改,只要它们都被限定在外部函数的相同版本上。

我们需要创建一个内部函数,以便外部函数中的变量在外部函数返回后有一些存在

考虑一个简单的函数:

函数f(){
var x=0;
return++x;//x=1
}//一旦函数退出,则“x”不再存在。
请注意,当程序控制从“f()”函数的开始流到它的结束时,变量“x”仅为“活动”(活动,存在)。但如果我们将“x”括在一个内部函数中,那么x将与该内部函数的寿命一样长:

函数g(){
var x=0;
返回函数(){
//现在“x”将和这个函数一样长。
return++x;
}
};
var计数器=g();
计数器();//=>1.
计数器();//=>2.
计数器();//=>3.
现在,当我们调用“g()”时,我们得到了另一个函数,只要该函数被变量引用,“x”就处于活动状态。

为什么要使用闭包

(function(){
    var current_page = 1;
    function previous_page() {
        current_page--;
        // update interface
    }
    function next_page() {
        current_page++;
        // update interface
    }
    // a bit of jQuery, ok?
    $('#previous').click(previous_page);
    $('#next').click(next_page);
})();

看:我们没有全局变量,甚至没有在全局空间中定义的任何函数。。。然而,我们为分页功能的“#上一页”和“#下一页”按钮的点击事件附加了一个行为。如果没有闭包,你会怎么做?如何定义函数中的当前页面变量?

关于闭包,有很多正确的答案,但它似乎总是非常技术化,而许多人可能会首先寻求更高层次的简单解释

我喜欢把它想象成一辆汽车。当你开车的时候,有很多复杂的过程在进行,但是普通人不需要在一个普通的日子里知道这些。可以将所有这些复杂的情况看作是隐藏在闭包中的“私有”变量,闭包使油门踏板、刹车、换档杆、方向盘等更易于使用


那么,关闭的目的是什么?隐藏所有复杂的变量,使脚本更易使用。如果每次你想使用脚本中的任何函数时都要担心脚本中的每个变量,那么这很快就会变得非常困难。耶

一个关于闭包的漂亮教程——我认为这是最好的一篇文章:你的意思是,即使我反复调用内部函数,其中的变量(从母函数创建的变量引用)仍然会被视为在以前调用时被修改过?因为我的想法是,在调用内部函数时,内部函数的变量仍然会从母函数中获取变量的值。因此,即使内部函数的变量是从母函数变量中引用的,内部函数的变量仍将是上次修改时的值?是和否。不能从外部函数引用内部函数中的变量,因此内部变量
   why to use:
when not to use
(function(){
    var current_page = 1;
    function previous_page() {
        current_page--;
        // update interface
    }
    function next_page() {
        current_page++;
        // update interface
    }
    // a bit of jQuery, ok?
    $('#previous').click(previous_page);
    $('#next').click(next_page);
})();