设置绑定脚本的执行顺序

Setting execution order of bound scripts

本文关键字:执行 顺序 脚本 绑定 设置      更新时间:2023-09-26

是否有办法控制绑定到元素点击的JS脚本的执行顺序?例如,我们有两个独立的脚本,它们针对相同的动作和相同的元素被触发。

第一个脚本(由网站上的脚本触发-我没有权限更改):

$('body').on('click', '#button', function1);

第二个脚本(它是由浏览器插件触发的,我可以改变它,并且会在其他一切都被触发后运行):

$('body').on('click', '#button', function2);

这两个脚本是分开的(在两个不同的文件中),不能像这样合并为一个,因为我只能更改第二个脚本:

$('body').on('click', '#button', function() {
    function1();
    function2();
});

可以设置执行顺序吗?我可以强制最后执行一个脚本吗?

在第二个脚本中,您可以读取第一个脚本绑定到click事件的函数。然后,您可以分离该处理程序并添加您自己的处理程序,您可以(如果您愿意)在最后一步中添加原始函数的执行:

// script 1 ///////////////////////////////////////////////////////////
function f1() {
    console.log('f1: function bound by script 1');
}
$('body').on('click', '#button', f1);
// script 2 ///////////////////////////////////////////////////////////
function f2() {
    console.log('f2: my own function that should run first');
}
var original_f = $._data(document.body, 'events').click[0].handler;
$('body').off('click', '#button').on('click', '#button', function () {
    f2();
    original_f();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="button">Trigger handlers</button>

这使用了$._data,它不是jQuery的公共API的一部分。请看这个答案

评论

上面的解决方案假设

  1. 网站的脚本(第一个脚本)使用jQuery事件委托的#button元素的body元素;如下:

    $('body').on('click', '#button', function1);
    

    注意,还有其他方法可以附加事件处理程序,但是这个答案假设第一个脚本是这样做的(正如您在问题中提供的那样)。当然,function1可以是任何函数,甚至可以是匿名的内联函数。

  2. 您可以完全控制第二个脚本,并可以重新定义您在其中定义的单击处理程序。

您在注释中写道,您无法访问第一个脚本(function1)的函数。但是请注意,如果JavaScript能够执行它,那么没有理由不能通过JavaScript访问它。

此外,由于您告知第一个脚本使用jQuery附加它们的处理程序,jQuery也知道它是哪个函数并可以访问它(否则如何在单击事件发生时执行它?)。

我上面提供的解决方案实际上要求jQuery为您提供该函数的引用。然后你可以像jQuery那样在点击事件发生时执行它。

测试处理程序是否存在

为了验证第一个脚本是否确实设置了一个处理程序,如下所示:
$('body').on('click', '#button', function1);

…它仍然存在,您可以使用以下脚本进行调试:

// script 1 -- you don't need to enter this, it is for this snippet to work with.
function f1() {
    console.log('f1: function bound by script 1');
}
$('body').on('click', '#button', f1);
// script 2 -- your code ///////////////////////////////////////////////////////////
var click_handlers = $._data(document.body, 'events').click;
console.log('Info on BODY click handlers that have been set via jQuery:'n',
             JSON.stringify(click_handlers, null, 2));
console.log('First click handler is this function:'n', click_handlers[0].handler);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>