这是否包含JavaScript闭包?

这是否包含JavaScript闭包?,javascript,jquery,closures,Javascript,Jquery,Closures,在尝试学习JavaScript闭包时,我有点困惑自己 从我在网上收集的信息来看,结束是 在另一个函数中声明函数,并且该内部函数可以访问其父函数的变量,即使在该父函数返回后也是如此 下面是最近一个项目中的一个小脚本示例。它允许通过按钮上下滚动div中的文本 var pageScroll = (function() { var $page, $next, $prev, canScroll = true, textHeight,

在尝试学习JavaScript闭包时,我有点困惑自己

从我在网上收集的信息来看,结束是

在另一个函数中声明函数,并且该内部函数可以访问其父函数的变量,即使在该父函数返回后也是如此

下面是最近一个项目中的一个小脚本示例。它允许通过按钮上下滚动div中的文本

var pageScroll = (function() {

    var $page,
        $next,
        $prev,
        canScroll = true,
        textHeight,
        scrollHeight;

    var init = function() {

        $page = $('#secondary-page');

        // reset text 
        $page.scrollTop(0);

        textHeight = $page.outerHeight();

        scrollHeight = $page.attr('scrollHeight');

        if (textHeight === scrollHeight) { // not enough text to scroll

            return false;    

        };

        $page.after('<div id="page-controls"><button id="page-prev">prev</button><button id="page-next">next</button></div>');

        $next = $('#page-next');

        $prev = $('#page-prev');

        $prev.hide();

        $next.click(scrollDown);

        $prev.click(scrollUp);

    };

    var scrollDown = function() {

        if ( ! canScroll) return;

        canScroll = false;

        var scrollTop = $page.scrollTop();

        $prev.fadeIn(500);

        if (scrollTop == textHeight) { // can we scroll any lower?

            $next.fadeOut(500);

        }

        $page.animate({ scrollTop: '+=' + textHeight + 'px'}, 500, function() {

            canScroll = true;

        });    

    };

    var scrollUp = function() {

        $next.fadeIn(500);

        $prev.fadeOut(500);

        $page.animate({ scrollTop: 0}, 500);    


    };

    $(document).ready(init);

}());
那么,如果我想让文本从JavaScript中的任何其他地方向下滚动,我可以这样做吗

pageScroll.scrollDown();
另一个更新
哇,看起来好像成功了!这是上面的代码。请注意,在本例中,页面滚动器并不完全起作用(它似乎没有进入文本的底部),但这没关系:)任何人都可以告诉我为什么它没有滚动到底部。

是的,确实有闭包。例如,您使用在范围之外声明的
$page、$next
等,例如
init
(使用它们)。

我不是Javascript专家,但从我在这里读到的内容来看,是的,您有闭包

请注意,例如,所有内部函数都共享变量$page。init分配给它,然后滚动函数更新它。所以原则上,内部函数是外部函数的闭包。外部函数将init传递给document.ready,因此以某种Javascript方式返回闭包


也就是说,我还必须说,这段代码是函数编程的一个非常糟糕的例子,因为纯函数不应该有副作用(比如分配给共享变量)。尽管如此,它还是有闭包。

我认为您没有使用任何闭包,因为您没有从外部函数返回内部函数,所以调用这些变量时,它们总是在范围内。换句话说,
init()
scrollDown()
scrolldup()
必须从
pageScroll()
中调用。如果
pageScroll()
返回其三个内部函数中的任何一个,然后在
pageScroll()
之外调用它们,则
$page
$next
$prev
等变量的使用将是闭包。我想。

今天不带我的Javascript:The Good Parts book开始工作真是太好了

我相信简短的回答是“不”,因为这部分定义是:“即使在父函数返回之后。”但我不是100%确定

不过,这可能会有所帮助

Javascript的YouTube剪辑:好的部分


您正在附加到
#page next
元素的
onclick
事件一个函数
scroll down
,该函数保留对对象
页面滚动
的变量
canScroll
的引用。因此,是的,您正在使用闭包


事实上,您的示例中有4个闭包:发送到
$next.click
、发送到
$prev.click
、发送到
$page.animate
、发送到
$(document)的函数。准备好了吗

是的,您确实有一个闭包,请看这个快速示例

         <script type="text/javascript">
    var t1=null;
    function test(){
        alert('Test');
        var x  = 10;
        t1 =  function(){
            alert('x='+ x);
        };  
    };
    function test2(){
        t1();
    }
    </script>
    <a href="javascript:test();">Test me 1 </a>  

<a href="javascript:test2();">Test me 2</a>

var t1=null;
功能测试(){
警报(“测试”);
var x=10;
t1=函数(){
警报('x='+x);
};  
};
函数test2(){
t1();
}

闭包可以访问其父变量,在本例中,我们的函数“t1”访问私有声明的var x;另外,正如您所说的“内部函数可以访问其父函数的变量,即使在该父函数已返回之后。”当您单击“Test me 2”时,您将收到一个x=10的警报,即使是函数Test()已返回的变量,这是否有意义。

是的,示例代码中有许多闭包。混淆可能来自于在定义中对闭包应用了过于严格的要求。虽然在闭包的生命周期内,闭包确实可以访问其绑定的自由变量,但闭包没有必要将这些变量的生命周期延长到其正常环境之外,从而将函数视为闭包

例如,假设我们有一个函数
findAllPeople
,它在一个列表中查找所有名字作为参数提供给函数的人。我们可以创建一个内部函数,该函数接受一个人并根据提供的名字测试他们的名字。该内部函数将有两个自由变量——即,要测试的person和name。要测试的名称绑定到提供给
findAllPeople
的参数。因此,内部函数在该自由变量上是闭合的。内部函数是在执行
findAllPeople
时创建、使用和丢弃的,并且没有在
findAllPeople
之外的任何地方使用,这一事实与内部函数是闭包的事实没有任何关系。

显然是的。。。 当你将一个函数嵌套在另一个函数中时,你有一个闭包。。 就这样


看看Dmitry a.Soshnikov关于ECMA-262(“javascript”)的博客系列

第6篇文章是关于闭包的,如果你阅读了之前的文章,你应该会很好地理解它

短篇故事是;函数声明或放置在函数(声明或表达式)中的函数表达式会将父函数范围添加到其范围链中。因此,它可以访问作用域链上每个函数中包含的所有变量(以全局作用域结尾)。但到目前为止,我们并不是在谈论结束

“闭包”的概念是在范围链之外创建对此类包含函数的引用时出现的,方法是返回对该函数的引用,或将对该函数的引用作为范围链中更高一级对象的属性添加。[因此,通过调用函数(通过该引用)可以修改隐藏在insi中的变量
         <script type="text/javascript">
    var t1=null;
    function test(){
        alert('Test');
        var x  = 10;
        t1 =  function(){
            alert('x='+ x);
        };  
    };
    function test2(){
        t1();
    }
    </script>
    <a href="javascript:test();">Test me 1 </a>  

<a href="javascript:test2();">Test me 2</a>
var func = (function(){
             var txt = 'Hi There!'
             return function(){
               alert(txt);
             }
           })();

 func(); //alert 'Hi There', eventhough the outter function has exit
        function test (value){
            return function(){
                alert(value); //using enclosed argument
            }
        }

        var t1 = test("first");
        var t2 = test("second");
        t1();//alerts "first"
        t2();//alerts "second"
function makeArray (){
    var result=[]
    for (var i =0; i < 3; ++i){
        result.push(function(){
            alert("function #" +i); //using enclosed i
        })
    }
    return result;
}

var fnArray =makeArray();
fnArray[0]();//alerts "function #3"
fnArray[1]();//alerts "function #3"
fnArray[2]();//alerts "function #3"
function makeArray (){
    var result=[]
    var wrapFunction=function (counter){
        return  function(){
            alert("function #" +counter); //using enclosed counter
        }
    }
    for (var i =0; i < 3; ++i){
        result.push(wrapFunction(i))
    }
    return result;
}

var fnArray =makeArray();
fnArray[0]();//alerts "function #0"
fnArray[1]();//alerts "function #1"
fnArray[2]();//alerts "function #2"