当前位置: 动力学知识库 > 问答 > 编程问答 >

javascript function redefinition

问题描述:

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.

网友答案:

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
网友答案:

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;
    }
})();
网友答案:

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?

网友答案:

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). What this really means is that at the time of execution, the function object that is getting executed and the original function definition are actually 2 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, it's 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(){return this.name;}
                    };
                }
            )();
            break;

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

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

console.dir(d);
d('A');
console.dir(d);
console.log(d.getName());
网友答案:

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).

网友答案:

Strictly speaking, no, it isn't possible to redefine a JavaScript function at all. Though it's kind of a matter of semantics.

A function may overwrite its reference within a certain scope with another function, which serves as a sleight of hand where another function appears in the place of the first. e.g.

greet_once = function() {
  console.log('Hello.');
  greet_one = function() { console.log('Can I help you?') };
};

Similarly a function may use the state of a closured scope to behave differently the second time its called (obviously not "redefinition").

The following example illustrates why the above pattern isn't redefinition because it depends on the parent scope which may not be shared with the calling scope.

greet_always = function() {
  greet_once = function() {
    console.log('Hello.')
    greet_one = function() { console.log('Can I help you?') }
  };
  return one_timer
}()

greet_always()
greet_always()

The function being called as greet_always (which always prints 'Hello.') is the same one, assigned originally to greet_once.

The closest I believe you can get to redefining a function is to reassign its apply and call methods, which produces a scenario where myFunction.call() is different from myFunction(), which is weird but conceivably useful.

分享给朋友:
您可能感兴趣的文章:
随机阅读: