【问题标题】:e.nodename undefined when using setTimeoute.nodename 使用 setTimeout 时未定义
【发布时间】:2017-09-26 18:25:57
【问题描述】:

我使用class='filt' 编写了这段代码,用于各种表格顶部的输入框,以允许根据这些输入过滤表格。当然,大多数输入都超过 1 个字母,所以我想添加一个计时器或类似的去抖动功能。下面的工作正常,但是当我添加计时器时,我开始得到一个

“e.nodename 未定义”

错误。有什么想法吗?

<script>
    var typingTimer;
    var doneTypingInterval = 1000;
    $('.filt').on('keyup', function () {
        var children = $(this).parent().parent().find("input");
        clearTimeout(typingTimer);
        typingTimer = setTimeout(function () {
            $("#table1 tbody tr").show();
            for (var i = 0; i < children.length; i++) {
                var tableChild = children[i];
                if (tableChild.value) {
                    var valarr = tableChild.value.split(",,");  //multiple filter separator 
                    for (var az = 0; az < valarr.length; az++) {
                        if (valarr[az].charAt(0) == '~') {   //negation operator
                            var val2 = valarr[az].substr(1);
                            $("#table1 tbody tr:not(:not(:has(td:eq(" + tableChild.id + "):contains('" + val2 + "'),td:eq(" + tableChild.id + ") [value*='" + val2 + "'])))").hide();
                        } else {                              //standard filter
                            $("#table1 tbody tr:not(:has(td:eq(" + tableChild.id + "):contains('" + valarr[az] + "'),td:eq(" + tableChild.id + ") [value*='" + valarr[az] + "']))").hide();
                        }
                    }
                    $("#table1 tbody tr").eq(0).show();
                }
            }
            $(this).focus();  //annoying extra code for MS browsers
            var thistext = $(this).val();
            $(this).val('').val(thistext);
        }, doneTypingInterval);
    });
</script>

【问题讨论】:

  • 没有人想搜索所有那些乱七八糟的代码。请减少它,或者至少告诉我们错误所在的行号。
  • 我想我找到了问题所在。最后是烦人的 MS 浏览器代码。它引用了 $(this),但我不知道如何解决这个问题。

标签: javascript jquery filtering


【解决方案1】:

在启动计时器之前,只需将this 放入另一个参数,如下所示。因为setTimeout 有自己的作用域。

<script>
        var typingTimer;
        var doneTypingInterval = 1000;
        $('.filt').on('keyup', function () {
            var children = $(this).parent().parent().find("input");
            clearTimeout(typingTimer);

            //Get this into self
            var self =  this;

            typingTimer = setTimeout(function () {
                $("#table1 tbody tr").show();
                for (var i = 0; i < children.length; i++) {
                    var tableChild = children[i];
                    if (tableChild.value) {
                        var valarr = tableChild.value.split(",,");  //multiple filter separator 
                        for (var az = 0; az < valarr.length; az++) {
                            if (valarr[az].charAt(0) == '~') {   //negation operator
                                var val2 = valarr[az].substr(1);
                                $("#table1 tbody tr:not(:not(:has(td:eq(" + tableChild.id + "):contains('" + val2 + "'),td:eq(" + tableChild.id + ") [value*='" + val2 + "'])))").hide();
                            } else {                              //standard filter
                                $("#table1 tbody tr:not(:has(td:eq(" + tableChild.id + "):contains('" + valarr[az] + "'),td:eq(" + tableChild.id + ") [value*='" + valarr[az] + "']))").hide();
                            }
                        }
                        $("#table1 tbody tr").eq(0).show();
                    }
                }
                $(self).focus();  //annoying extra code for MS browsers
                var thistext = $(self).val();
                $(self).val('').val(thistext);
            }, doneTypingInterval);
        });
    </script>

【讨论】:

    【解决方案2】:

    这是一个上下文问题。您正在引用 this,认为它指向 .filt 元素,但您没有意识到超时回调会将上下文更改为 window

    $('.foo').on('click', function() {
        this; //is the clicked element
        setTimeout(function() {
            this; //is window
        }, 1);
    });
    

    有几种方法可以引用不同的this。 jQuery 的 .bind() 允许您将 callbcak 与您喜欢的任何 this (即元素)关联起来。

    $('.foo').on('click', function() {
        this; //is the clicked element
        setTimeout(function() {
            this; //is also element
        }.bind(this), 1); //<-- note bind()
    });
    

    或者,您也可以通过立即执行的函数将外部 this 作为函数参数传递给超时回调:

    $('.foo').on('click', function() {
        this; //is the clicked element
        setTimeout((function(outer_this) { return function() {
            outer_this; //is also element
        }; })(this), 1);
    });
    

    或者只是在进入超时之前创建一个引用它的变量:

    $('.foo').on('click', function() {
        var outer_this = this; //<-- cache outer scope
        this; //is the clicked element
        setTimeout(function() {
            outer_this; //is also element
        }, 1);
    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多