Skip to content Skip to sidebar Skip to footer

Javascript Function Redefinition

Is it possible to redefine a JavaScript function from within its own body. For example, could I do the following? function never_called_again(args) { // Do some stuff never_cal

Solution 1:

It is indeed possible to redefine a function from its body. The technique is used in the so-called Lazy Function Definition Pattern.

It looks like this:

// Lazy Function Definition Patternvar foo = function() {
    var t = newDate();
    foo = function() {
        return t;
    };
    returnfoo();
}

This function stores the Date of the first call, and returns this Date afterwards.

If you compare this with the module pattern, the difference is that the initialization only happens when it's first called, not when it's defined. For costly initializations it can be a huge benefit.

// Conditional Module Patternvar foo = (function() {
    var t;
    returnfunction() {
        if (t) {
            return t;
        }
        t = newDate();
        return t;
    }
})();

Solution 2:

Yes, you can redefine a function that way.

Running This:

functionnever_called_again(args) {
    console.log('Func 1', args);

    never_called_again = function (new_args, x) {
        console.log('Func 2', new_args, x);
    }
}

never_called_again('arg A', 'arg B');

never_called_again('arg A', 'arg B');

Yields this:

Func 1 arg A
Func 2 arg A arg B

Solution 3:

It's totally possible to redefine a function object into whatever you want upon the first call.

The reason this is possible is because the assignment evaluations is handled from right to left. This means that the scope of the function is captured when you execute it (in this case, when you call the function).

This really means that at the time of execution, the function object that is getting executed and the original function definition are actually two different things, which allows redefinition of the original function as, well... anything really.

One of the best (and coolest) ways to use this is by creating a function that is, in essence, its own factory. In this way you don't have to carry around a lot of object definitions that aren't going to be used.

Example:

d = function(type){
    switch(type.toUpperCase()){
        case'A' :
            d = (
                    function(){
                        return {
                            name : 'A',
                            getName : function(){returnthis.name;}
                        };
                    }
                )();
                break;

        case'B' :
            d = (
                function(){
                    return {
                        name : 'B',
                        getName : function(){returnthis.name;}
                    };
                }
            )();
            break;

        default:
            d = (
                function(){
                    return {
                        name : 'DEFAULT',
                        getName : function(){returnthis.name;}
                    };
                }
            )();
            break;
    }
};

console.dir(d);
d('A');
console.dir(d);
console.log(d.getName());

Solution 4:

Your example is basically the same as:

var never_called_again = function(args) {
     //do some stuff
     never_called_again = function (new_args) {
      //do some new stuff
     }
}

Since you probably know that this works:

var a = 1;

function myFunction() {
     //do some stuff
     a = 2;
}

myFunction();

alert(a) //==> 2

it's clear that the first example works too.

Whether you actually want to do this or not is a more open question. Will it make the code harder to understand?

Solution 5:

Yes, it's possible, and it will not create a global function. I verified this in Internet Explorer 6, Firefox, Chrome, and Opera. Consider the following code:

<head><title>Never called again</title><styletype="text/css"></style><scripttype="text/javascript">functionhello()   {
             functionnever_called_again(args) {
                alert("Hello world " + never_called_again);
                //do some stuff
                never_called_again = function (new_args) {
                    //do some new stuffalert("hello " + never_called_again);
                }
             }
             never_called_again();
             never_called_again();

          }

      </script></head><bodyonload=""><buttononclick="hello(); never_called_again();">Call</button></body>

This will print "Hello World {function code}" the first time of the never_called_again and the second time it will print "hello {changed function code}" the second time.

But when it's being called on button's onclick, it will throw an error saying that the function is not defined, clearly indicating that the function was re-defined (and not created globally).

Post a Comment for "Javascript Function Redefinition"