This jsfiddle演示了我尝试实现的基本模型。点击链接后,我应该可以将鼠标悬停在列表元素上,文本应该出现在页面上,但它们不会出现。当我打印应该出现的字符串的值时,它们是未定义的。"为什么会这样?
这是以下的js,但我建议看一下小提琴。
$('#link1').click(function () {
var foolist = ["foo1", "foo2", "foo3"];
for (var i = 0; i < foolist.length; i++) {
var li = document.createElement('li');
li.innerHTML = "This is a link.";
$(li).hover(function () {
console.log(foolist[i]);
$('#p1').append(foolist[i]);
},
function () {});
$('#ul1').append(li);
}
});
答案 0 :(得分:2)
您已经发现需要一种叫做封闭的东西!恭喜 - 没有多少人看到他们有多酷。这是pulled from a great MSDN article - 我强烈建议您阅读其余内容。
问题是,i
变量不再具有您调用.hover
时所执行的值 - 如果您记录它,则会看到i===3
。那为什么会这样?您传递给.hover
的函数是一个闭包 - 这意味着它由函数本身和一种&#34;快照&#34;组成。 .click
函数的范围。您可以在循环的每次迭代中创建一个闭包,但它们都共享相同的&#34;快照&#34;。当您尝试通过click事件访问i
时,循环已经完成。
那你怎么解决呢?更多关闭!
function showText(i) {
$('#p1').append(foolist[i]);
}
function makeTextCallback(i) {
return function() {
showText(i);
};
}
for (var i = 0; i < foolist.length; i++) {
$(li).hover(makeTextCallback.call(this,i));
}
这被称为&#34;功能工厂&#34;。您将i
发送给makeTextCallback
,该i
会在其返回的闭包内捕获C:\wamp\www\Node_JS\mysql>node server.js
Listening on 3000
A user is connected!
A user is connected!
C:\wamp\www\Node_JS\mysql\node_modules\mysql\lib\protocol\Parser.js:82
throw err;
^
TypeError: Cannot read property 'release' of undefined
at C:\wamp\www\Node_JS\mysql\server.js:37:14
at Handshake.onConnect (C:\wamp\www\Node_JS\mysql\node_modules\mysql\lib\Pool.js:54:9)
at Handshake.Sequence.end (C:\wamp\www\Node_JS\mysql\node_modules\mysql\lib\protocol\sequences\Sequence.js:96:24)
at Handshake.ErrorPacket (C:\wamp\www\Node_JS\mysql\node_modules\mysql\lib\protocol\sequences\Handshake.js:103:8)
at Protocol._parsePacket (C:\wamp\www\Node_JS\mysql\node_modules\mysql\lib\protocol\Protocol.js:274:23)
at Parser.write (C:\wamp\www\Node_JS\mysql\node_modules\mysql\lib\protocol\Parser.js:77:12)
at Protocol.write (C:\wamp\www\Node_JS\mysql\node_modules\mysql\lib\protocol\Protocol.js:39:16)
at Socket.<anonymous> (C:\wamp\www\Node_JS\mysql\node_modules\mysql\lib\Connection.js:96:28)
at Socket.emit (events.js:107:17)
at readableAddChunk (_stream_readable.js:163:16)
。
答案 1 :(得分:1)
简单的规则是避免循环中的任何闭包。
另一个好方法是在data
属性中定义这样的东西:
$('#link1').click(function () {
var foolist = ["foo1", "foo2", "foo3"];
foolist.forEach(function(x) {
$("<li/>")
.data('list', x)
.text("This is a link");
.hover(fooListItemOnHover, fooListItemOnHoverOff)
.appendTo('#ul1');
}
});
function fooListItemOnHover() {
var data = $(this).data('list');
console.log(data);
$('#p1').append(data);
}
function fooListItemOnHoverOff() {
}
这将生成具有额外data-list
属性的元素,该属性将存储您的自定义数据:
<li data-list='foo1'>This it a link</li>
然后,您的脚本将使用jQuery data()
从其中读取此数据。
答案 2 :(得分:0)
使用jQuery的.data()方法将任何类型的数据附加到DOM元素。
$('#link1').click(function () {
var foolist = ["foo1", "foo2", "foo3"];
for (var i = 0; i < foolist.length; i++) {
var $li = $("<li/>");
$li.data("VAL", foolist[i]);
$li.html("This is a link.");
$($li).hover(function () {
var value = $(this).data("VAL");
console.log(value);
$('#p1').append(value);
},
function () {});
$('#ul1').append($li);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<a id="link1" href="javascript:;">Click to show list</a>
<ul id="ul1"></ul>
<p id="p1"></p>