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