为什么javascript代码在循环内工作,一旦代码被提取到一个单独的函数
Why did javascript code inside loop work once the code was extracted to a separate function?
我在jQuery插件中编写了以下代码,用于制作标记云。我传入一个格式为[{tag: "028", count: 15}, {tag: "101", count: 357}]的数据数组。我现在正在创建云作为跨度,根据计数规范化大小。span的创建是正确的,即它们具有正确的大小和文本。我添加了一些事件,点击和鼠标事件。无论单击哪个span,它总是显示数组中最后一个元素的警告。
在尝试调试正在发生的事情时,我将元素创建代码提取到一个单独的函数中。一旦我这样做了,点击事件正常工作,即点击事件显示了什么跨度被点击的正确数据。
我假设两个版本会产生相同的结果。为什么点击事件工作一旦我提取元素创建到它自己的函数?
这是不能工作的版本:
for (var i = 0; i < tagList.length; ++i) {
if (tagList[i] != null) {
var tagValue = tagList[i].tag;
var tagCount = tagList[i].count;
var size = getNormalizedSize(tagCount);
var theSpan = getText(tagValue, tagCount); // <span style="font-size: {1}em">{0}<'/span>
var theAlert = getAlert(tagValue, tagCount); // "Project {0} is has logged in {1} drawings"
var newElement = $(theSpan);
newElement.click(function() {
alert(theAlert); // Always shows data from last element in array
}).mouseenter(function(event) {
$(this).css('backgroundColor', '#FFC');
}).mouseleave(function() {
$(this).css('backgroundColor', '#FFF');
});
this.append(newElement).append(" ");
}
}
这是有效的版本:
for (var i = 0; i < tagList.length; ++i) {
if (tagList[i] != null) {
var tagValue = tagList[i].tag;
var tagCount = tagList[i].count;
var tagElem = buildElement(tagValue, tagCount);
this.append(tagElem).append(" ");
}
}
function buildElement(tagValue, tagCount) {
var size = getNormalizedSize(tagCount);
var theSpan = getText(tagValue, tagCount); // <span style="font-size: {1}em">{0}<'/span>
var theAlert = getAlert(tagValue, tagCount); // "Project {0} is has logged in {1} drawings"
var newElement = $(theSpan);
newElement.click(function() {
alert(theAlert);
}).mouseenter(function(event) {
$(this).css('backgroundColor', '#FFC');
}).mouseleave(function() {
$(this).css('backgroundColor', '#FFF');
});
return newElement;
}
在每个处理程序中捕获相同的变量,其作用域为循环。然后,当调用处理程序时,它包含分配给它的最后一个值。当您将其移动到函数中时,该变量的作用域为该函数调用的实例,因此它对于循环的每次迭代都是不同的,并且在该迭代中具有分配的值。
这是因为两个解决方案有不同的作用域规则。在第一种情况下,没有函数调用,这意味着theAlert
只定义一次,您只需更新click
回调处理程序引用的引用。在第二种情况下,您通过调用buildElement
来创建一个新的作用域,在这种情况下,这意味着theAlert
是为列表中的每个标记定义的,并且仅在定义时更新,因此每个click
闭包引用不同的变量。
click
callback)在运行之前不会被解析。下面是一个简单的例子来说明这一点:
var name = 'John';
setTimeout(function(){ alert(name); }, 1000);
name = 'Joe';
因此,即使当引用name
的闭包在值更改之前创建时,它实际上不是运行,直到稍后,因此将被警告的名称是"Joe"而不是"John"。
相关文章:
- Regex代码只允许一个空格
- 从我的控制器返回一个不同于200的代码以触发ajax错误,这被认为是一种好的做法吗
- 代码背后调用一个JavaScript函数的按钮点击-C#
- 创建一个循环来简化HTML和CSS代码
- 如何创建更好的方式来维护基于我的代码访问的最后一个页面
- 简单的垂直上一个和下一个按钮代码点击上下移动jQuery
- 我需要一个jQuery函数来只工作在700px以上的屏幕大小,无法在我的代码中发现错误
- 调试一个简单的jQuery函数;想知道是否与其他代码冲突
- 解析云代码作业:删除在数据库中已经存在一个小时的行
- 在单击下一个按钮之前,在JavaScript代码中添加5秒的延迟
- 代码挑战:创建一个跟踪对象实例总数的类Foo
- 有没有一个Javascript代码可以看到你的缓存有多满
- Jquery时间启动计时器,我有一个计时器的代码,但它在页面加载时启动
- 我在下拉列表中尝试了下一个和前五年的html代码.接下来的5年我都过得很好.我怎样才能拿到之前的5年
- jQuery将代码合并为一个函数
- jQuery toogle-一个打开,另一个隐藏-在代码中的任何位置
- 如何在jquery中为object键创建一个工作变量以避免额外的代码
- 使用一个 jquery 代码关闭多个模态
- 在一个JavaScript文件中解析云代码定义和作业
- html或java脚本代码在硬盘中创建一个文本文件