获得悬停的价值会产生" undefined"

时间:2015-11-10 03:10:51

标签: javascript jquery html

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);
    }
});

3 个答案:

答案 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)

https://jsfiddle.net/aLofhaxp/28/

答案 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>