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 和 Waypoints 获取 $this 的 ID