1

To help understand this the function is in the html page and it is generated, I cannot change the generated code:

function Update_qu7260() {
  var newVal = ''
  for( var idx = 0; idx < 2; idx++ )
  {
    var test
    if( idx == 0 ) test = text7263
    else if( idx == 1 ) test = text7265
    if( test.matchObj ) newVal += test.leftSel + "-" + test.matchObj.rightSel + ","
  }
  newVal = newVal.substring( 0, newVal.length-1 )
  VarQuestion_0001.set( newVal )
  qu7260.hasBeenProcessed=false;
  doImmFeedback('qu7260');
}
var qu7260 = new Object();
...
qu7260.updFunc = Update_qu7260;
var qObj=[qu7260];

Note in the above the number "7260", the numbers start at 1 so there are lots of them and each Update_###() will be different so I cannot re-write them with "hard wired" code. My code is in an external JavaScript file and is executed onLoad:

...
var updFunc = qObj[0].updFunc.toString();
if(updFunc.indexOf('doImmFeedback(')!=-1){
  updFunc = updFunc.replace('doImmFeedback','doImmQuestionFeedback');  // do my function
  updFunc = updFunc.replace('function ','');  // remove the word function
  var funcName = updFunc.substr(0,updFunc.indexOf('('));  // get the function name e.g. Update_qu7260
  updFunc = "window['" + funcName + "']=function" + updFunc.replace(funcName,'');
  eval(updFunc);
}
...

When I change the eval() to alert() I can see the that it's correct, however, the eval() is not raising any errors and my function doImmQuestionFeedback is not being called. When I subsequently do an alert(qObj[0].updFunc.toString()) I see the original function.

It would seem that I have provided information that is too complex, so the following code is a better example:

function hi(){alert('hi');}
function changeHi(){
   hi(); // I get an alert box with hi
   newHi = "function hi(){alert('hi there');}"
   eval(newHi);
   hi(); // I get an alert box with hi
   window.setTimeout('hi()',500); // I get an alert box with hi
}
window.setTimeout('changeHi()',500);

The following is the original question:

I have a predefined function that I did not create, however, I know it's name so I can get the function itself and then I change it by doing:

var funcText = window.updateFunc.toString();
funcText = funcText.replace('doSomeOtherFunction(','doMyFunction(');

How do I update the actual function so it will do all that it did before except it will now call doMyFuntion()?

The following is an example to help visualize what I want to do, the actual function I need to change is very complex. I have:

function updateFunc(whatToUpdate,true){
   ... - do lots of stuff.
   var retVal = doSomeOtherFunction(whatToUdate);
   ... - do lots of stuff based on retVal
}

I need to change this to:

function updateFunc(whatToUpdate,true){
   ... - do lots of stuff
   var retVal = doMyFunction(whatToUdate);
   ... - do lots of stuff based on retVal, I have had a chance to change retVal
}

Then the first thing my function will do is call doSomeOtherFunction() check/change the returned value and subsequently return the value to the updateFunc().

I have tried to manipulate the funcText above to:

funcText = 'window.updateFunc = function(...';
eval(funcText);

Without success.

1
  • I found the problem, all my fault, sorry about that. Note the line qu7260.updFunc = Update_qu7260;, once I change the function I then need to put it back in the object again, I thought it was just a pointer but it was the function itself and that is triggered elsewhere via this.updFunc(). Commented Jan 17, 2016 at 3:31

5 Answers 5

1

This may be closed enough to what you are looking for.

Assuming you have this original function:

function originalFunc(val) {
    // this function converts input string to upper case
    return val.toUpperCase();
}

Now you want to override it to something either before or after you execute that function (in this example, we execute before, of course before or after doesn't matter in this case).

// we preserve orignal function
var originalFunc_save = originalFunc;

// now we override the original function with this block    
var originalFunc = function(text) {
    // lets call the orignal function
    text = originalFunc_save(text);

    // now do our custom thing
    return text.split('').reverse().join('');
}

So our test should work.

var text = 'This is a test';
console.log(originalFunc(text));

Output:

TSET A SI SIHT

This method also works if you have to override functions inside a class. The only thing we have to be careful of is to choose a saved name that doesn't interfere with the original class code. _save may not be good enough, but you get the idea.

UPDATE: I'm updating this code above to use a string variable pointing to the original function. I think this is what the OP wanted.

Original code which defined by some library

function originalFunc(val) {
    // this function converts input string to upper case
    return val.toUpperCase();
}

Now we use the func string variable to point to that function and execute it.

var text = 'This is a test';
var func = 'originalFunc';
text = window[func](text);
console.log(text);

Output: Of course we get the original intended result because we haven't overridden it.

THIS IS A TEST

Now we write our code to override the original function behavior using a string pointing to the function.

// let's define a new function string
var funcSaved = func + '___saved';

// now preserve the original function code
window[funcSaved] = window[func];

// override the original function code block
window[func] = function(text) {
    // lets call the orignal function
    text = window[funcSaved](text);

    // now do our custom thing
    return text.split('').reverse().join('');
}

// let's test the code
text = 'This is a test';
text = window[func](text);
console.log(text);

Output:

TSET A SI SIHT
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for this, however, all of your code is hard wired, I have a string variable and I need that to become a function. I actually don't know the name of the function as it is part of another object. e.g. funcText = obj1234.updateFunc.toString();
Oh, I thought you do know what the original function name is, but even if you need to override a function which is referenced by a string variable, still doable. Let me re-read your post and come up with the code using a variable.
@Peter - Your second statement says you know the function name, but that doesn't matter. :)
@Peter - I just realized what you're asking. If you want to change the content of the original function. I don't know if you can. The way to do such thing is to override it.
0

You can make a clone of updateFunc function, edit it at your discretion and work with it in what follows.

    function updateFunc(whatToUpdate, param){ // the initial function
        ...
        var retVal = doSomeOtherFunction(whatToUpdate);
        return retVal;
    }

    // formation of unnamed function as string
    var newfunc = updateFunc.toString().replace('function updateFunc', 'function ').replace('doSomeOtherFunction(', 'doMyFunction(');

    function doMyFunction(whatToUpdate){ // your new function, just for example
        console.log(parseInt(whatToUpdate) * 10);
    }

    var newUpdateFunc;
    // declaring new version of 'updateFunc' function
    // which is stored in 'newUpdateFunc' variable 
    eval("newUpdateFunc = " + newfunc); 

    newUpdateFunc(3); // outputs '30'

Comments

0

I believe this is a valid use case for the forgotten JavaScript with feature.

Basic idea: you call original updateFunc supplying your own version of doSomeOtherFunction to it using with namespace injection:

function updateFunc(whatToUpdate,true){
   ... - do lots of stuff.
   var retVal = doSomeOtherFunction(whatToUdate);
   ... - do lots of stuff based on retVal
}


function patchUpdateFunc() {

  var original_doSomeOtherFunction = window.doSomeOtherFunction;
  var original_updateFunc = window.updateFunc;

  function doMyFunction() { 
    // call original_doSomeOtherFunction() here,
    // do your own stuff here.
  };

  window.updateFunc = function() {
    with ({doSomeOtherFunction: doMyFunction}) {
       return original_updateFunc.apply(this, arguments); 
    }
  }
}

patchUpdateFunc();

2 Comments

@Peter If you think that you made it simpler then not. You have two unrelated pieces of code there (old and new).
OK, can you help with the new?
0

I think you are going at this way too complicated. If you only have doMyFunction and doSomeOtherFunction to switch between, you could just create a flag somewhere telling you to use one or the other when used in an if-statement.

If you want to call a function with a name you do not know beforehand and you only get a name during runtime, you could either accept the function to call as a parameter or accept the name of the function as a parameter and call it like so: var retVal = window[functionName](); (assuming functionName is a property of the window object).

I would highly recommend directly accepting a function as a parameter since the function may not be defined in a global scope.

EDIT: After your clarification, I think, I can give you a satisfying answer:

if you have a string like var functionString = "function updateFunc(whatToUpdate){var retVal = doMyFunction(whatToUpdate);}";

You can define a function using a Function object: window.updateFunc = new Function("whatToUpdate", "return (" + functionString + ")(whatToUpdate)"); This will replace the already existing function and you can give it any valid function string you want as long as you know and specify the arguments.

4 Comments

Thanks for you input, however, what I have asked is what I need an answer for. Basically I have a string variable that contains a function and I want it to become a function, I also need it to replace an existing function. This is very complex and the code is an example - thanks.
Check the edit above, I think, I got what you wanted now.
The new function is in a string variable, you have hard wired code.
My code takes a string variable functionString containing the function and replaces the old function. Isn't that exactly what you want? P.S. It doesn't exactly do what you want because it wraps the function inside an anonymous function but that shouldn't be a problem, right?
0

If I understood correctly, you want to override the external function. You can achieve that with the following code

//Someone else's function
function externalFunction(foo){
    return "some text";
}

//Your function
function myFunction(value){
  //Do something
}

//Override
var externalFunction = (function(){
    var original = externalFunction; //Save original function

    return function(){
        var externalFunctionReturnValue = original.apply(this, arguments);

        return myFunction(externalFunctionReturnValue);
    }
})();

I strongly sugest not to use eval, but since you want to parse javascript from string:

function hi(){alert('hi');}
function changedHi(){
   hi(); // I get an alert box with hi
   newHi = "window['hi'] = function(){alert('hi there');}"
   eval(newHi);
   hi(); // I get an alert box with hi there
   window.setTimeout('hi()',500); // I get an alert box with hi there
}
window.setTimeout('changedHi()',500);

UPDATE:

This code snippet works which is your original code:

  <script type="text/javascript">
     function doImmFeedback(foo){
        console.log("DoImmFeedback: " + foo);
      }

      function Update_qu7260() {
        console.log("Some code")
        doImmFeedback('qu7260');
      }
   </script> 

    <script type="text/javascript">
      var qu7260 = new Object();
      qu7260.updFunc = Update_qu7260;
      var qObj=[qu7260];

      var updFunc = qObj[0].updFunc.toString();
      if(updFunc.indexOf('doImmFeedback(')!=-1){
        updFunc = updFunc.replace('doImmFeedback','doImmQuestionFeedback');  // do my function
        updFunc = updFunc.replace('function ','');  // remove the word function
        var funcName = updFunc.substr(0,updFunc.indexOf('('));  // get the function name e.g. Update_qu7260
        updFunc = "window['" + funcName + "']=function" + updFunc.replace(funcName,'');
        console.log(updFunc);
        eval(updFunc);
      }

      function doImmQuestionFeedback(foo){
        //Your function
        console.log("doImmQuestionFeedback: " + foo);
      }

      Update_qu7260(); //This executes your doImmQuestionFeedback
   </script>

So if your function isn't running, your function isn't in the global scope, or something else is happening, and we can't know if don't have any more info. Check your developer's console for javascript errors.

8 Comments

Maybe my question title is all wrong? I need to build a function in a variable and then convert that variable to an actual function - thanks.
I strongly suggest not to use eval, but if your variable contains valid javascript, your code should work; eval('function test(){ console.log("foo"); }'); test(); So please post your full code or give us more info ;)
With my code you can achieve exactly that, you want to change the first function, my code does exactly that... Have you tested it?
Sorry about this but your code is all hard wired, it must be from a string variable - thanks.
@Peter I edited my answer with your example working.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.