jQuery 使用 $(this) 作为 setInterval/setTimeOut 函数内的起点遍历 DOM?

Posted

技术标签:

【中文标题】jQuery 使用 $(this) 作为 setInterval/setTimeOut 函数内的起点遍历 DOM?【英文标题】:jQuery traversing the DOM using $(this) as a starting point inside setInterval/setTimeOut function? 【发布时间】:2021-07-30 07:36:58 【问题描述】:

我一直在尝试了解如何(在 jQuery 中)使用 $(this) 作为 setInterval/setTimeOut 函数中的起点来遍历 DOM,并且遇到了一些我觉得莫名其妙的行为。

似乎不可能使用 $(this) 作为 setInterval/setTimeOut 函数内的起点来遍历 DOM

为什么会这样? jQuery/javascript 人 - 开始吧。

用于说明行为的示例代码:

jQuery:

// set this code anywhere (inside/outside - document.ready/named-function/...) and run it
var autoTimer = setInterval(function()
    // INSERT EXAMPLE TEST-CODE FROM BELOW HERE
, 10000)

已尝试测试代码:

// from inside the setInterval/setTimeOut function above
// if $(this)
if($(this).length !== 0) 
    alert('hello');
 // alerts hello

// from inside the setInterval/setTimeOut function above
// if html-tag (body/head/html)
if($('body').length !== 0) 
    alert('hello');
 // alerts hello

// from inside the setInterval/setTimeOut function above
// if className
if($('.className').length !== 0) 
    alert('hello');
 // alerts hello

// from inside the setInterval/setTimeOut function above
// if id
if($('#id').length !== 0) 
    alert('hello');
 // alerts hello

所以它可以很好地找到文档中的特定元素,除了 $(this) 你可以从那里遍历 DOM

即。

// from inside the setInterval/setTimeOut function above
if ($('.className').find(something).length !== 0)... // works just fine

当你想使用 $(this) 作为起点进行遍历时,问题就来了

尝试以$(this)为起点遍历测试代码:

// from inside the setInterval/setTimeOut function above
// traversing up the DOM
if($(this).parents('body').length !== 0) 
    alert('hello');
 // no alert (same with closest/parentsUntil/etc up the DOM)

// from inside the setInterval/setTimeOut function above
// traversing sideways in the DOM
if($(this).siblings('body').length !== 0) 
    alert('hello');
 // no alert (same with next/prev/etc sideways in the DOM)

// from inside the setInterval/setTimeOut function above
// traversing down the DOM
if($(this).find('body').length !== 0) 
    alert('hello');
 // no alert (same with children down the DOM)

因此,从 $(this) 'body'(或其他任何东西)开始似乎不存在任何地方(向上/向下/横向),从上面的任何其他起点来看都是不正确的

我也尝试使用命名的全局函数,如下所示:

// set outside/inside document.ready
function testCode() 
    // INSERT EXAMPLE TRAVERSING TEST-CODE FROM ABOVE HERE


// set this code anywhere (inside/outside - document.ready/named-function/...) and run it
var autoTimer = setInterval(testCode, 10000) // no alert

// set this code anywhere (inside/outside - document.ready/named-function/...) and run it
var autoTimer = setInterval(function()
    testCode();
, 10000) // no alert

所以重申我的问题: 为什么在 jQuery 中使用 $(this) 作为起点来遍历 setInterval/setTimeOut 中的 DOM(上/下/横向)似乎是不可能的?

还有哪些可能的黑客/变通方法/等。对于这种行为?

黑客/变通办法/等的可能非解决方案。

this answer 使用 $.proxy 仅在您使用旧版本的 jQuery 时才有效 - 但由于 as this document attests 'This API has been deprecated in jQuery 3.3'... 目前这不是一个解决方案。

bind 方法也不是,因为文档证明“从 jQuery 3.0 开始,.bind() 已被弃用”并被 on 方法取代(但我看不出我将如何使用.on() 在这里有任何效果 - 但也许这只是因为我缺乏想象力)。

【问题讨论】:

请向我们展示出现问题的实际代码。您已经向我们展示了很多代码,但实际上没有一个在 setTimeout 中包含 this。如果您没有实际向我们展示过代码,那么很难向您展示如何修正您的代码。 我试着让它更通用,因为这种行为让我感到困惑,我想要更通用的基本解释来解释为什么它没有按预期工作(在下面接受的答案+获取实际代码的用例工作)但这就是为什么提供更通用的代码(哦,它是 setInterval 而不是 setTimeout - 尽管我怀疑两者的答案是相同的):) - 但根据建议,在问题中添加了一个编辑 【参考方案1】:

这是一个基本的this 作用域问题,与 jQuery 关系不大。

最直接的方法是将this 分配给回调之外的另一个变量

var that = this;

setInterval(function () 
    $(that).parents();
, 1000);

如果你不关心 IE,或者如果你有构建过程,你可以使用箭头函数,它使用外部范围的this

setInterval(() => 
    $(this).parents();
, 1000);

我个人的偏好是完全避免使用 this,因为它的所有 cockamamie 行为让你非常悲伤。从您的示例中不清楚您的 this 值来自何处,但这里有一些方法可以避免它:

// inside .each()
$('a').each(function (_, el) 
    $(el).parents();
);

// inside event handler
$('a').on('click', function (event) 
    $(event.target).parents();
);

【讨论】:

很好...效果完全符合预期...我会研究您的替代方案-但非常感谢...您不知道我在这上面花了多少时间搜索/阅读和尝试建议的解决方案都会得到我的支持和复选标记:)

以上是关于jQuery 使用 $(this) 作为 setInterval/setTimeOut 函数内的起点遍历 DOM?的主要内容,如果未能解决你的问题,请参考以下文章

使用on()jQuery方法将'this'作为参数传递给事件处理程序

JQuery $this 选择器 - 如何使其工作

如何使用 jQuery 和 Waypoints 获取 $this 的 ID

QPainter and QPen

Android 设置视图位置 - setY vs setTop

使用 jQuery getJson 发送列表/数组作为参数