为什么我的'this'不会在每个循环中改变内部jQuery中的上下文?

时间:2011-12-14 17:49:49

标签: javascript jquery this each method-chaining

我的想法是,我想循环遍历这些对象并构建一个将添加到页面的HTML结构。我认为在链条中完成这一切会更干净,但显然我不了解this的内容,因为它通过内部循环演变。我看了一下jQuery.proxy(),但我不确定我是否理解如何应用它。也许还有另外一种方法可以做我在这里尝试做的事情......

var obj = [
    {"id":1213854620001,"name":"item 1","URL":"1213897576001.jpg"},
    {"id":1213854619001,"name":"item 2","URL":"1213890384001.jpg"},
    {"id":1213854618001,"name":"item 3","URL":"1213890378001.jpg"},
    {"id":1213854616001,"name":"item 4","URL":"1213897663001.jpg"},
    {"id":1213854615001,"name":"item 5","URL":"1213897554001.jpg"}
];
$(function() {
    if(obj.length) {
        $("<ul/>",{id:"myID"}).append(function(){
            var that = document.createDocumentFragment();
            $.each(obj,function(index,dataObj){
                $("<li/>",{data:{dataID:dataObj.id},text:dataObj.name}) // this === obj[index] === dataObj, shouldn't it be the [object HTMLLIElement]
                    .live("click",function(event) {
                        openVideo($(event.target).data(dataID));
                    })
                    .append(function() {
                        return $("<img/>",{src:dataObj.thumbnailURL})[0];
                    })
                    .appendTo(that);
            });
            return that;
        }).appendTo("body");
    }
});

function openVideo(str) {
    //console.log(str);
}

隐含的问题变成了,为什么that在循环后为空?以及如何使用嵌套循环构建此HTML结构?

使用评论和答案中的建议,我构建了这个,它似乎完全正常工作,读得更清洁,让jQuery做所有的javascript(例如documentFragment创建和操作,等):

$(function() {
    if(obj.length) {
        $("<ul/>",{id:"myID"})
        .delegate("li","click",function(){openVideo($(this).data("dataID"));})
        .append(function() {
            var that = $(this);
            $.each(obj,function(index,dataObj) {
                $("<li/>",{data:{dataID:dataObj.id},text:dataObj.name}).each(function() {                   
                    $("<img/>",{src:dataObj.URL}).appendTo(this);
                    that.append(this);
                })
            });
        }).appendTo("body");
    }
});

3 个答案:

答案 0 :(得分:4)

当您进入新的嵌套函数时,

this会发生变化。当您致电$()创建新元素时,会改变含义。

紧接着

$.each(obj, function(index, dataObj) {

this是您循环的当前对象。到达这里后:

.live("click",function(event) {  // <------  inside of nested function 
    openVideo($(event.target).data(dataID));
})

this是您点击的元素。

但是打电话给

    $("<li/>",{data:{dataID:dataObj.id},text:dataObj.name}) 

创建新的li元素this设置为新创建的元素。


此外,如果您想在嵌套函数内部保存this的含义,标准方法是将其保存为新变量。

$.each(obj, function() {
    var self = this;

现在可以使用self代替this作为循环中任何位置“当前”的项目,即使在嵌套函数处理程序中也是如此。或者您可以将index和dataObjects传递给每个函数 - 效果相同。

修改

正如评论指出的那样,你使用不正确。如果你正在使用jQuery 1.7,你会想要:

$(document).on("click", "li", function(event) {
      openVideo($(this).data(dataID));
});

document.ready处理程序中。如果所有将被点击的li将在某个div中,而不是选择该div而不是document。如果你不希望这个点击处理程序适用于所有li,但只有一些,那么装饰所有你希望这个点击处理程序应用于css类的li,然后将过滤器“li”传递给{{1你要通过on

答案 1 :(得分:1)

$.each设置this使内部函数成为迭代的元素(是的,this是Javascript中复杂的事情之一,但您的注释可以通过引用来解释each行为)。

答案 2 :(得分:0)

问题是,在基于原型的语言中,javascript是一个,函数是对象,对象具有属性。因此,当您使用'this'关键字时,它将恢复到当前原型的范围。在“内联函数”(实际上它不是javascript中的概念,因为函数只是对象)中,这是指函数。