这个问题已经在这里有一个答案:
- JavaScript的闭包内环路-简单实用的例子 42个回答
代码给我:A B C
当我点击ABC它总是显示我的最后一个“伏特加”。 我想 “马丁”(对于A), “林赛”(对于B), “伏特加”(对于C)
请帮我在我的例子。
myArray = [
{
letter: "A",
brand: "martin"
},
{
letter: "B",
brand: "lindsay"
},
{
letter: "C",
brand: "vodka"
}
];
var list = '';
for (var i = 0; i < myArray.length; i++) {
list += "<br>" + myArray[i].letter;
new_info = myArray[i].link;
(function(new_info) {
$(this).click(function(){ //this - refers to A or B or C
$('#box2').text(new_info);
});
}).call(this, myArray[i])
}
$('#box1').append(list);
编辑:
我说我不打算写你的代码为你......嗯,我所做的: 这个小提琴确实你在寻找什么。 我解决了上下文(发行this
),闭合问题和隐含的全局。 它仍然需要大量的工作,但小提琴说明了什么大家一直说的: $(this)
不会,不能,也永远指向一个字符串常量像"A", or "B"
。
遗憾地这样说,但你的代码是完全的问题,但我会满足你问这里的具体问题。
在循环中,你要指定一个点击处理程序,基本上是这样的:
function()
{
$('#box2').text(new_info);
}
其中new_info
是在较高的范围内声明的变量。 到现在为止还挺好。 问题是,你正在创建没有自己的任何值变量( 拷贝函数对象new_info
)发生的只是创建功能时举行。 相反,该函数引用变量。 因此,当任何这些功能被调用它$('#box2').text(new_info)
将被解析为$('#box2').text("whatever value new_info holds when function is called")
而不是$('#box2').text("whatever value new_info was holding when function was created")
您可以通过简单地添加第二个功能,你的代码给副本每个回调访问:
$(this).click((function(currentNewInfo)
{
return function()
{
$('#box2').text(currentNewInfo);
}
}(new_info)));
我正在这里做的是创造一个功能,那需要一个参数,并立即调用它。 我通过new_info
作为参数,这样的价值currentNewInfo
是什么new_info
认为在那个时候(又名复印件)
我叫(IIFE - 或立即调用函数表达式)函数返回实际的回调。 在此回调,我不引用new_info
,但IIFE的说法: currentNewInfo
。
由于每个函数都有自己的范围内,该变量被封闭 (故名闭合 ),并且不能被访问或从外部改变。 仍然可以访问的唯一的事情currentNewInfo
变量是IIFE返回的功能。
也许你担心名称冲突(每次创建回调使用引用currentNewInfo
),但事实并非如此:每次回调是由一个单独的函数创建的,因此可以访问不同的范围。 这是不可能有范围之间的名称冲突不互相访问...只是使事情非常简单的理解:
Where /\ and /\
|| ||
is return function() is scope of IIFE
因此,关闭访问函数的作用域返回后。 该范围的优先级,当涉及到解析为一个值的表达式。 为了更好地理解,这里有一个类似的图给你看JS 如何解析表达式:
其中每一个粉红色的“外部环境记录”是一个功能的范围(即已经返回或函数当前功能的关闭范围被调用)。 最后的环境要么是全局对象,或者为空(在严格模式下)。 这里的所有都是它的。
老实说,闭包是棘手首先让你的头一轮,但一旦你掌握了我所要在这里解释,他们是伟大的乐趣。
检查此链接 ,我可以去解释的使用情况和效益,嵌套关闭工作的方式,但我最终会写一本书。 我张贴的链接做了伟大的工作,在解释关闭使用相当愚蠢的图纸是如何工作的。 它可能看起来幼稚,但他们实际上帮助我,当我试图抓住的lambda函数,关闭和范围外过着函数调用的概念很多。 以上是从页所采取的图我的联系,这也解释了概念更深入了一点,但我仍然认为简单的,原油图纸都会自行解释。
其他问题:
正如有人指出的:“你希望this
参考”。 纵观片段, this
将只是参考全局对象( window
),将相同/相似的事件处理程序window
如果你问我根本就没有意义。
全局变量是邪恶的 , 隐含的全局更是如此。 我看不到new_info
,也不myArray
什么地方做声明。 JS解析表达式的方法是一点点遗憾,并回落到创建全局变量,没有这么多窥视:
var bar = 666;//global, always evil
function createGlobal()
{
var local = 2;
foo = bar * local;
}
createGlobal();
让我们来看看foo
:
JS is in createGlobal scope: var local is declared, and assigned 2.
foo is used, and assigned bar*local
|| || \\=>found in current scope, resolves to 2
|| ||
|| \\=>found in global scope, resolves to 666
||
||
||=> JS looks for foo declaration in function scope first, not found
||
||=> moves up 1 scope (either higher function, or global scope)
||
\\=>Global scope, foo not found, create foo globally! - hence, implied global
\\
\\=>foo can now be resolved to global variable, value undefined
过多的DOM查询:你的事件处理程序回调看起来都像这样:
$('#box2').text(new_info);
这( $('#box2')
实际上是一样的书写document.getElementById('#box2')
这实际上是英语。 想想看这样的:每个客户端点击时间$(this)
-不管它可能是,你所访问的DOM,并与给定的ID扫描它的元素。 为什么不这样做一次 ,并使用保存在内存中的引用更改文本。 这不仅节省了无数的DOM queries.You 可以使用一个变量,或者(在我关于关闭解释光),封闭:
var list = (function(box2, list, i)
{//list & i are arguments, so local to scope, too
for (i = 0; i < myArray.length; i++)
{
list += "<br>" + myArray[i].letter;//<-- don't know why you use this
//new_info = myArray[i].link; no need for this var
$(this).click((function(new_info)
{//new_info is closure var now
return function ()
{//box2 references DOM element, is kept in memory to reduce DOM querying
box2.text(link);
};
}(myArray[i].link));//instead of new_info, just pass value here
}
return list;//return string, assign to outer variable
}($('#box2'), ''));//query dom here, pass reference as argument