Stop execution of Javascript function (client side) or tweak it

前端 未结 5 2067
别跟我提以往
别跟我提以往 2020-11-22 08:48

I want to stop the execution of one single line from a site, so that the whole page is read by the browser except that single line. Or the browser may simply skip the execut

5条回答
  •  情书的邮戳
    2020-11-22 09:12

    Method 1: using MutationObserver

    beforescriptexecute no longer works in Firefox, nor did it work in Chrome. Luckily, there's an alternative, using MutationObserver, which is quite widely supported. The general idea is to add a MutationObserver at the beginning of pageload, which will run a callback whenever a new node is added to the DOM. Inside the callback, check for the existence of the

    Example content

Here's an example userscript that blocks jQuery from loading in the here on Stack Overflow:

// ==UserScript==
// @name             Example jQuery removal
// @include          https://stackoverflow.com*
// @run-at           document-start
// @grant            none
// ==/UserScript==

if (document.head) {
  throw new Error('Head already exists - make sure to enable instant script injection');
}
new MutationObserver((_, observer) => {
  const jqueryScriptTag = document.querySelector('script[src*="jquery"]');
  if (jqueryScriptTag) {
    jqueryScriptTag.remove();
    observer.disconnect();
  }
})
  .observe(document.documentElement, { childList: true, subtree: true });

If you install this, you'll see that the loading of jQuery fails, resulting in lots of errors generated by Stack Overflow's JS.

Make sure to attach the MutationObserver as soon as possible - you need @run-at document-start to attach it before the page loads anything inside the . (If using Tampermonkey / Chrome, you may need to enable experimental instant script injection to achieve this reliably - go to Tampermonkey Settings, Config mode: Advanced, scroll to the bottom, set Experimental Inject Mode to Instant.)

If you're writing userscripts for others, any you're using this technique, make sure to include instructions for instant script injection, since injection is not instant by default on Chrome.

Note that the observer is attached using

.observe(document.documentElement, { childList: true, subtree: true });

This attaches the observer to the element, watches for added and removed immediate children with childList: true, and watches for added and removed nodes anywhere inside its descendants with subtree: true. Such a recursive listener is useful, but it's also computationally expensive on large dynamic pages, so make sure to remove it once it's achieved its purpose.

On a huge page, calling querySelector on every mutation could be costly, so you might want to iterate through the mutations (the first parameter to the observer's callback) and the mutations' addedNodes instead:


Example content

You can also tweak inline scripts by assigning to their textContent inside the observer callback. The following snippet shows how you can change a random number generator function to always return 10, rather than 1-6:



Results:


Method 2: using DevTools Local Overrides

Method 1 is the technique you can use when writing userscripts for others. But if the userscript is just for yourself, there's an easier method that can work in some situations. See this answer to the question Chrome Dev Tools - Modify javascript and reload: by going to the Sources -> Overrides tab in Chrome Devtools, and enabling local overrides, you can tell the browser to load a local copy of a .js instead of downloading the site's version. Then you can edit the local copy as desired, and it'll run instead of the built-in script. This is especially useful when tweaking large Javascript files - it's much more manageable than the MutationObserver approach.

But, there are some downsides:

  • To modify inline tags, you'll have to download a local copy of the page. (So if the page serves dynamic content through the HTML response, you'll either have to re-save and re-tweak the .html for your overrides to use the new content, or you'll have to go back to the MutationObserver method.)
  • This is a technique developers may be able to understand (after some experimenting), but it's not so user-friendly. It may not be the sort of thing you'd want to walk a casual userscript consumer through.

提交回复
热议问题