-2

I superficially understand how functions are overridden in javascript ... the last method loaded (with the same name -- no signatures) is executed.

My web page add on is distributed as a js script. As part of it's functionality, a third party script calls a method 'x()' when it's loaded. Consumers of my add on may already have an x() method on their web page to interact (in their own way) with that third party script. If they don't though, I want to execute mine. Problem being that my x() overrides theirs, which is not the behaviour wanted.

Personally I think it's a bit crazy, with web latency, to override functions with 'last one rules' . Guess, that's another story.

Fortunately, I can look for a specific div and know that the client will have their own x() method and have conditionally added my method as a separate script. That way my method is only present on the page if theirs is not.

Is there a more elegant way of doing this? Effectively I'd like an x() that underrides the client's x(). I'm concerned that as some point I will not be able to easily check for their x(). Btw ... checking for the presence of x() using typeof === 'function' just returns true for my x().

Stephan Luis
  • 911
  • 1
  • 9
  • 24
  • 7
    Check for an existing `x` *before* you create yours. – Pointy Oct 01 '20 at 13:27
  • @Pointy was going to suggest the same thing :) – Alexandre Elshobokshy Oct 01 '20 at 13:27
  • as your code is an add-on, it should have its own scope in order to avoid conflicts with coexisting JS variables and, in general, prevent global scope polution. Use scoping, like IIFE to achieve this – benas123798 Oct 01 '20 at 13:29
  • @Pointy Would but needs to be global. Declared before a self-invoking method. – Stephan Luis Oct 01 '20 at 13:30
  • @Benediktas that would be nice, but have looked at that and don't see any way with the third party library and client scripts. Partly to keep my 'api' interface simple. Don't want to have user to pass their functions to me. It gets really sloppy. – Stephan Luis Oct 01 '20 at 13:32
  • That it's global is already the problem, but you can definitely do it. Test for `window.x` before you create your function, and if `window.x` was already a function have your own function delegate to it instead of running your code. – Pointy Oct 01 '20 at 13:33
  • Another way to go around this is if you just don't name your function `x`. Then check if the webpage has `x`--if it does, don't run your other function, if it doesn't, run your other function. This won't work, though, if you can't change the function name. But @Pointy's solution seems simpler, and is probably a better way. – marsnebulasoup Oct 01 '20 at 13:33
  • @Pointy I've tried like [fiddle](http://jsfiddle.net/huZG2/6/) originally from [SO](https://stackoverflow.com/a/5409468/2455159). Is that what you mean? – Stephan Luis Oct 01 '20 at 13:37
  • @StephanLuis yes exactly. There are a couple of variations but it''s basically the same idea: look for what you might step on first, then adjust accordingly. – Pointy Oct 01 '20 at 13:39
  • @Pointy Tried that in my IIFE, but not as global. I can see as 'global' that it might work. – Stephan Luis Oct 01 '20 at 13:43

1 Answers1

2

Global namespace pollution is a terrible thing. It's wrecking families and destroying our cities. However, in this case, you can mitigate the problem:

let existingX = window.x || undefined;
function x(whatever) {
  if (existingX && typeof existingX == 'function') {
    existingX(whatever);
  }
  else {
    // all of your version of x
  }
}

If you like, you can use a more obscure name than "existingX" to avoid yet another collision.

Another option might be:

var x = window.x && typeof window.x == 'function' ? window.x : function(whatever) {
  // your code
};

Of course if the existing x is something other than a function that intends to override yours, there's not much you can do except maybe console.log() a stern warning.

Pointy
  • 405,095
  • 59
  • 585
  • 614