tags:

views:

85

answers:

5

Is it possible to redefine a javascript function from within it's own body. For example could I do the following:

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

Is the above valid and does it have the correct semantics? I don't want to create a new global variable with the old function name because I'm trying to do this kind of thing not in the global scope but from various object scopes and I don't want name clashes when I redefine the function within those local scopes.

A: 

I don't think you can redefine a function within itself since you would change it as it execute

Kaaviar
+1  A: 

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?

Douglas
A: 

Yes, you can redefine a function that way.

Running This:

function never_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
Brock Adams
thanks for **copying my answer**... lol
galambalazs
@galambalazs: I gave you credit and I expanded on aspects you didn't cover to my satisfaction. Additionally, my first answer and main answer had nothing to do with yours and was sufficient.
Brock Adams
It's **not a community wiki**. Global variables has nothing to do with function redefinition, they are only related to the Lazy Func. Definition pattern, which is an example for function redefinition. Everything is explained well in the link btw... But again it was only an example. Your answer was to tight and got no votes that's why you've changed it...
galambalazs
@galambalazs: No, before I changed it, I had as many votes as you (1 each) -- before I upvoted you. I changed my answer to make it more complete, incorporating lessons from the article you cited that you didn't. Furthermore I gave you credit. I've seen other people do this. It's supposed to be about improving answers, not silly snits. By your logic, Peter Michaux should be after you for plagiarism. Anyway, I've rolled back my answer
Brock Adams
`1.` What you're talking about is community wiki, when they may gather the answers into one collection. But this thread is not one of them. `2.` Have you've seen other people killing innocents? Do you imitate them? Just because other people do something doesn't mean it's right. You should be clever enough to know that. `3.` It's supposed to be about answering a question in the best way you could, not about gathering the best of all answers and edit them into one.
galambalazs
+4  A: 

It is indeed possible to redifine a function from it's body. The technique is used in the so-called

Lazy Function Definition Pattern

It looks like this:

// Lazy Function Definition Pattern
var foo = function() {
    var t = new Date();
    foo = function() {
        return t;
    };
    return foo();
}

What this function does is it 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 Pattern
var foo = (function() {
    var t;
    return function() {
        if (t) {
            return t;
        }
        t = new Date();
        return t;
    }
})();
galambalazs
Nice one. snip 8<---
mplungjan
Thanks for the link it was pretty interesting and I'm using the pattern in a similar kind of way to avoid various conditional execution paths.
davidk01
+1  A: 

Yes its possible and it will not create a global function. I verified this in IE6, FF, Chrome, Opera. Consider the following code:

  <head>
     <title>Never called again</title>
     <style type="text/css">
     </style>

     <script type="text/javascript">

          function hello()   {
             function never_called_again(args) {
                alert("Hello world " + never_called_again);
                //do some stuff
                never_called_again = function (new_args) {
                    //do some new stuff
                    alert("hello " + never_called_again);
                }
             }
             never_called_again();
             never_called_again();

          }

      </script>

  </head>
  <body onload="">

     <button onclick="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 its being called on button's onclick, it will throw error saying that the function is not defined, clearly indicating that the function was re-defined (and not created globally).

naikus