这是否包含JavaScript闭包?

ale*_*lex 10 javascript jquery closures

在尝试学习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);

}());
Run Code Online (Sandbox Code Playgroud)

这个例子是否使用闭包?我知道它在函数中有函数,但是有没有使用保留的外部变量的情况?

我在不知情的情况下使用它们吗?

谢谢

更新

如果我把它置于$(document).ready(init);声明之下,这会成为一个闭包吗?

return {
    scrollDown: scrollDown
};
Run Code Online (Sandbox Code Playgroud)

那么,如果我想让文本从JavaScript中的任何其他地方向下滚动,我就可以做到

pageScroll.scrollDown();
Run Code Online (Sandbox Code Playgroud)

另一个更新

哇,看起来很有效!这是JSbin上的代码.请注意页面滚动器在这个示例中并不完全有效(它似乎没有出现在文本的底部),但是没关系:)任何可以告诉我它为什么不滚动到底部的人的奖励积分.

Mar*_*ter 12

每当你定义一个函数时,该函数将"包围"它所定义的范围链.当执行该函数时,范围链在其体内可用.当在另一个函数内定义函数时,作用域链包括:

  • 父函数的本地定义变量
  • 父函数的参数
  • 父函数的父函数的本地变量和参数等.
  • 全局变量

闭包的真正价值在于返回一个内部函数,该函数捕获了一个不会改变的封闭变量,如下所示:

        function test (value){
            return function(){
                alert(value); //using enclosed argument
            }
        }

        var t1 = test("first");
        var t2 = test("second");
        t1();//alerts "first"
        t2();//alerts "second"
Run Code Online (Sandbox Code Playgroud)

闭包的一个危险是它们包含对所包含属性的引用,而不是它们的值的快照,因此请注意在循环内创建一个封闭函数,如下所示:

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"
Run Code Online (Sandbox Code Playgroud)

在循环中,您需要找到一种方法来使您的封闭变量保持不变.下面是使用嵌套闭包将重用计数器复制到单次使用参数的示例:

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"
Run Code Online (Sandbox Code Playgroud)