不完全了解此关闭的工作原理
Not fully understanding how this closure works
我摘自 JavaScript 闭包如何工作?
我很难理解闭包。
<button type="button" id="bid">Click Me!</button>
<script>
var element = document.getElementById('bid');
element.onclick = (function() {
// init the count to 0
var count = 0;
return function(e) { // <- This function becomes the onclick handler
count++; // and will retain access to the above `count`
if (count === 3) {
// Do something every third time
alert("Third time's the charm!");
//Reset counter
count = 0;
}
};
})();
如何在调用之间保存"计数"值?不应该通过 var = 0 重置每次调用吗?
在回答你的问题之前,首先让我们讨论一下你的代码是如何工作的:
当你在另一个函数中定义一个函数时,它会创建一个clouser。在 clouser 内部,内部函数可以访问外部函数范围,我的意思是外部函数的变量和参数,即使外部函数已返回。在您的代码中,外部函数是一个立即调用的函数。这意味着它在定义后立即被调用。当它返回时,内部函数被分配给onclick事件。单击函数可以访问,以及修改外部函数的变量(in this case
count
which is defined in the outer function)
即使它返回。我已经在您的代码中注释掉了。通过它,就会清楚
首先,立即调用函数(function(){...})()
函数将立即调用。它返回另一个函数。所以剩下的是一个返回的函数,它将分配给 onclik 处理程序。所以,返回后它将是
var element = document.getElementById('bid');
element.onclick =function(e) { // <- This returned function has becomes the onclick handler
count++; // it can access the outer function's count variable and modify it even if the outer function returns.
if (count === 3) {
// Do something every third time
alert("Third time's the charm!");
//Reset counter
count = 0; // it can also reset outer function's count variable to zero
}
};
如何在调用之间保存"计数"值?不应该重置吗 var 的每个调用 = 0?
右。如果您一次又一次地使用此代码以及立即调用的函数,则每次计数都将以零开头。但是,如果您一次又一次地单击相同的按钮,您可以看到它的美丽。即使外部函数已返回,内部函数也可以访问其变量。因此,每次单击按钮时,它们都会被修改
第一次点击按钮将打印1,所以计数现在是1。第二次单击将再次修改它并打印 2,依此类推。请记住,在 clousers 中,即使外部函数返回,内部函数也可以访问外部函数的变量。因此,内部函数没有任何计数变量。它只是访问外部作用域的变量。因此,第三次单击后,它将再次分配给零。
var element = document.getElementById('bid');
var mydiv=document.getElementById('mydiv');
element.onclick = (function() {
// init the count to 0
var count = 0;
return function(e) { // <- This function becomes the onclick handler
count++;
mydiv.innerHTML+=count+'</br>'; // and will retain access to the above `count`
if (count === 3) {
// Do something every third time
mydiv.innerHTML +="Third time's the charm!</br>";
//Reset counter
count = 0;
}
};
})();
<button type="button" id="bid">keep clicking me </button>
<div id='mydiv'></div>
如果这样声明:
element.onclick = function() {
var count = 0;
};
您是对的,每次单击count
都会初始化为 0。
但是,它是这样声明的:
element.onclick = (function() {
var count = 0;
return function(e) {
count++;
...
};
})();
在这种情况下,onclick
处理程序已分配给函数的结果,即:
return function(e) {
count++;
...
};
因此,count
在单击事件期间不会初始化为 0。
count
是代码中第一个函数的本地函数。 由于第二个函数位于该函数内,因此count
可用。
正如您所说,您的函数成为 onclick 处理程序,并且计数的分配者仅执行一次(当您的函数创建并分配给单击处理程序时)。计数仍在函数的范围内,即函数保留一个引用并使用该引用。因此,它不会重置和递增。
思考的方式:
var count = 0;//Belongs to the window
//object and I like to imagine a window object
//around it so that you can see
//that everything in javascript is enclosed!
function() {count++};
我很确定您在理解上述代码时没有任何困难。现在想象一下以下内容:
var count = 0; //Belongs to the window
function x() {
var count = 0;//Private to function x
(function () {
count++;
alert(count);//What will this output?
})();
};
x();
alert(count);//And this?
您将看到第一个将输出 1,第二个将输出 0,为什么:因为它们是不同的变量。它们彼此无关。这就是为什么人们喜欢在javascript中做闭包的原因。如果污染了全局名称空间,则可以覆盖它。
var count = 0; //Belongs to the window
function x() {
var count = 0;
(function () {
count++;
alert(count);
})();
};
x();
alert(count);
var count= 1;//Global count has now been overwritten
alert(count);
你声明一个立即调用的函数,语法如下:
(function() {
...
})();
这仅在首次加载时运行一次。
返回的代码:
return function(e) { // <- This function becomes the onclick handler
count++; // and will retain access to the above `count`
if (count === 3) {
// Do something every third time
alert("Third time's the charm!");
//Reset counter
count = 0;
}
};
是实际成为点击处理程序的内容。因此,每次单击时仅运行返回函数中的代码。
由于在 Javascript 中处理作用域的方式,内部函数可以访问外部函数中的变量。您可以通过使 count 变量全局化来实现类似的功能,但这种模式的好处是它限制了全局变量,并且还为变量提供了隐私。来自立即调用函数外部的任何调用都无法访问计数。
外部函数(括在括号中的函数)是立即调用的函数表达式的示例。该函数同时被定义和调用,其返回值是分配给element.onclick
的值。
那么,当我们可以直接将element.onclick
设置为内部函数时,为什么要为此烦恼呢?嗯,这与JavaScript范围规则有关。获取私有作用域的唯一方法是将某些内容包装在函数中。在这里,count
在外部函数中声明和初始化,有效地使其成为私有的。内部函数仍然可以访问和操作它。这就是术语闭包的全部含义 - 一个内部函数访问其封闭函数的变量。
外部函数只调用一次(立即),因此count
只初始化为 0 一次。但是变量保留在内存中,不会被垃圾回收,因为 JavaScript 足够聪明,知道内部函数仍然需要访问它。
- Angularjs:了解如何工作$location
- 我根据解决方案按类对
- 元素进行分组,但需要帮助了解它的工作原理
- 了解 JavaScript 对象实例或工作流
- 不了解这种返回语句是如何工作的
- 不完全了解此关闭的工作原理
- 了解服务工作进程范围
- 如果可能的话,我需要帮助了解这个jQuery过滤器函数是如何工作的,逐行工作
- 了解 JS .match() 工作
- 了解document.getElementByClassName的工作原理 - Javascript
- 了解嵌套组件绑定在 KnockoutJS 上的工作原理
- 试图了解 D3 .data 键函数的工作原理
- 需要了解跟踪代码在网页内容中的工作方式
- 试图了解猫鼬如何繁殖或加入工作
- 了解数据消除属性在Bootstrap中的工作原理
- 我没有'我不了解$(this)jQuery对象是如何工作的
- 了解$.proxy如何在内部工作
- 试图了解表单是如何工作的,以及为什么document.location.htm无法正常工作
- 了解eclipse项目的性质和web开发的工作流程
- 试图了解函数回调是如何工作的
- 试图了解如何html GET和res.redirect工作在express