-1

Can I, in JavaScript, add a function to an already existing function or object that a function within that object then "suddenly" can "see" and call itself? Here is an example to demonstrate:

function CreateThing() {
  function callAddedFunction() {
    theFunction(); // this does not exist yet!
  }
}

So theFunction() obviously does not exist in createThing(). Is there any way to add that outside so that when I then invoke callAddedFunction() it is able to resolve that? Something like:

let f = new CreateThing();
addFunctionAtRuntime(f, "theFunction", function() {
    console.log("YAY!");
};
f.callAddedFunction();

I have tried to experiment with prototype, but I have been unable to do this. Note that the main reason for me wanting to do this is "fake" object inheritance without resorting to classes and inheritance as that requires the this keyword in front of every function call. I also want to avoid having to pass an object in that function as a parameter that can be called through in order to reach those other functions. I know that I can achieve this by having all those extra functions in global scope, but I have hoped to avoid that if possible.

EDIT: I have modified my example with the magic function I was looking for called addFunctionAtRuntime which from what I have understood is not possible. Some suggest I use eval and just make those functions available in the eval script, but so far I have been able to do this by creating a script tag dynamically and add my code as content including those functions I wanted callAddedFunction() in my example above to be able to see (without having to call through some object context).

Johncl
  • 1,211
  • 1
  • 12
  • 13
  • 1
    You cannot inject a function (or any object, for that matter) into the closure of `CreateThing` from outside. – Heiko Theißen Jan 07 '23 at 17:35
  • Is the name of the function to inject known beforehand? – Bergi Jan 07 '23 at 20:49
  • "*I want to do "fake" object inheritance*" - could you expand on what you mean by that, please? I don't get your use case. "*requires the `this` keyword in front of every function call*" - can you show a solution that uses the `this` keyword to demonstrate how you want your injection to work? Also I don't see what's wrong with using `this`, you're doing OOP after all – Bergi Jan 07 '23 at 20:54
  • This keyword is needed if I instead of using a function use a class. Then in order to access any function I need to have this.theFunction() for example (where theFunction is the inherited). I wanted to see if there was some way to have the same feature as class inheritance but without the need for this as it adds clutter in my case. – Johncl Jan 07 '23 at 21:55
  • You need to use `this` to call a method, regardless whether the method was defined using `class` syntax or not, and regardless whether it is inherited or not. But really it would help if you could [edit] your question to provide an example of how you like your code to look, including all of the initial definition, the inheritance, and the use of the method. – Bergi Jan 07 '23 at 23:07
  • My example plainly shows how I want it to be. The callAddedFunction needs to be able to call some function that is not defined "yet", but if possible could be added outside to the object. theFunction() does not exist yet but if it was in global context it would have worked. Is there any way to "inject" functions so that they resolve when method callAddedFunction() is called? From what I understand it might not be possible. – Johncl Jan 07 '23 at 23:39
  • 1
    No, the example is incomplete, it does not show how `callAddedFunction` is exposed or invoked. `CreateThing` could as well be an empty function. Also I still fail to see what this has to do with "inheritance", I'm missing to spot the second entity (class?) from which something is inherited. – Bergi Jan 07 '23 at 23:43
  • 1
    Also, why are you not simply passing the `theFunction` as a constructor parameter to `CreateThing`? – Bergi Jan 07 '23 at 23:45
  • The point is for the class to be a kind of script where you can easily call functions that are added after but without having to call through a passed object or this, like class in heritance which works fine btw but then you have to write this in front of every function call you want. For now I will just use functions in global context then although that is not really what I wanted. I added a call to callAddedFunction() to make it clear that this is called outside after. – Johncl Jan 09 '23 at 13:01
  • I don't see what this has to do with inheritance or how you would achieve this with class inheritance. But really, it sounds like the solution is to just use `this.`, it doesn't hurt! – Bergi Jan 09 '23 at 13:30
  • You can then simply inherit a class with all your functions you want to "inject" and they are reachable as if they were part of this class, although though they keyword this all the time. The question is basically if there was some magical way to avoid "this" or call functions through an object - only for making the code cleaner/simpler. – Johncl Jan 09 '23 at 14:24
  • You can use the `with` statement, but that makes code only shorter, not cleaner or simpler. – Bergi Jan 09 '23 at 15:31
  • Yes I know about the with statement but I wanted to avoid that. My goal with my question was in fact to make the code shorter. I solved it by dynamically creating a script tag, add the function/class as content and append whatever functions I wanted it to see as if it was in global/window context. It is a hack that works for now. Many suggested eval which could work as well but it has some limitations. – Johncl Jan 24 '23 at 14:38
  • @Johncl I'd think that a dynamic script tag has more limitations than `eval` actually – Bergi Jan 24 '23 at 14:46

2 Answers2

0

Just in case the OP ...

  • ... is not in need of something as complex as method modification as described / demonstrated at e.g.

  • ... why doesn't the OP just provide the very function object as parameter to the Thing constructor at the thing object's instantiation time?

    After all it comes closest to (or is exactly) what the OP describes with ...

    Can I, in JavaScript, add a function to an already existing function or object that a function within that object then "suddenly" can "see" and call itself?

    function Thing(fct) {
      this.callAddedFunction = () => fct();
    }
    const thing = new Thing(() => console.log("YAY!"));
    
    thing.callAddedFunction();
Peter Seliger
  • 11,747
  • 3
  • 28
  • 37
  • I wanted my function to be some kind of script that is able to call functions as if they were in window/global scope, but actually added later dynamically to the function or class. In my example theFunction(); is the call to such a function. So far I have only been able to do this by creating a script tag dynamically and actually adding these functions to the scope of that script by injecting their code into that as content. When callAddedFunction() is then called it is able to find theFunction() then. – Johncl Jan 24 '23 at 14:33
  • @Johncl ... the OP might think about providing a better comprehensible use case ... e.g. what functions/methods are like originally and how the OP wants them to function after having altered each of its behavior. – Peter Seliger Jan 24 '23 at 14:57
0

I'm not sure this is exactly what you want but you can also use a generic higher-order function that returns the implementation you are looking for.

   const supplimentor = (src, extraFunc) => ({
      src: new src(), 
      extraFunc
    })

    //OR

    function supplimentor1(src, extraFunc) {
      this.extraFunc = extraFunc;
      new src();
    }
    
  function CreateThing() {console.log('SOURCE')}
  const extraFunc = () => console.log('EXTRA');
  
  const newFunc = supplimentor(CreateThing, extraFunc)
  newFunc.extraFunc()

  const newFunc1 = new supplimentor1(CreateThing, extraFunc)
  newFunc1.extraFunc()
Djtouchette
  • 395
  • 2
  • 6