[removed] inline functions vs predefined functions

前端 未结 13 1857
心在旅途
心在旅途 2020-12-02 11:00

Can any body throw me some arguments for using inline functions against passing predefined function name to some handler.

I.e. which is better:

相关标签:
13条回答
  • 2020-12-02 11:46

    I know, that this is an old question, but to me there is an even more important difference than the ones already mentioned. hoisting Every function has to be created and therefore reserves some space in memory and eventually has to be GC later.

    Named functions get hoisted to the beginning of the surrounding function, and are therefore created on every function call, wether they get used or not. Anonymous functions get created only if the code that defines them is executed.

    //an example where you wold prefer to use an anonymous function.
    //you can assign this (anonymous) function to a variable, so you get your "name" back.
    function someFn(){
        if(condition){
            //the variable declaration has been hoisted, 
            //but the function is created at this point, and only if necessary.
            var process = function(value){/* */};
            switch(condition2){
                case 1: process(valueFor1); break;
                case 2: process(valueFor2); break;
                /* ... */
            }
        }
    }
    
    function someFn(){
        var process;
        if(condition){
            process = function(value){ /* A */ }
        }else{
            process = function(value){ /* B */ }
        }
    
        //beware, depending on your code, "process" may be undefined or not a function
        process(someValue);
    }
    
    
    //an example where you would prefer (/ utilize) the hoisting.
    function someFn(){
        /* some code */
        while(condition){
            //some might want to keep the function definition near the code where it is used,
            //but unlike an anonymous function or a lambda-expression this process-function 
            //is created only once per function-call, not once per iteration.
            function process(value, index){ /* ... */ }
            /* ... */
            process(value, index)
        }
    }
    

    so, as a rule of thumb:

    • inside a loop there should be no anonymous function or lambda-expression

    • if you need the function only inside of a (rarely true) condition you should prefer anonymous functions over named ones, since they are only created when needed

    • if you know your buisness (JavaScript), you know when to ignore this advice

    0 讨论(0)
  • 2020-12-02 11:47

    Named functions

    There is some serious misuse of terminology in the question and answers on this page. There is nothing about whether or not a function is inline (a function expression) that says you cannot name it.

    This is using a function expression:

    setTimeout(function doSomethingLater() { alert('In a named function.'); }, 5);
    

    and this is using a function statement:

    function doSomethingLater() { alert('In a named function.'); }
    setTimeout(doSomethingLater, 5);
    

    Both examples are using named functions and both get the same benefits when it comes to debugging and profiling tools!

    If the name is specified (the text after "function" but before the parenthesis) then it is a named function regardless of whether it is inline or declared separately. If the name is not specified then it is "anonymous".

    Note: T.J. points out that IE mishandles named function expressions in a non-trivial way (See: http://kangax.github.com/nfe/#jscript-bugs) and this is important to note, I'm simply trying to make a point about the terminology.

    Which should you use?

    In response to your direct question, you should use a named function statement if the function could ever be used from any other place in your code. If the function is being used in exactly one place and has no relevance anywhere else then I would use a function expression unless it is prohibitively long or otherwise feels out of place (for style reasons). If you use an inline function expression then it is often useful to name it anyway for the purposes of debugging or code clarity.

    Memory leaks

    Whether you name your function, use a function statement, or use a function expression has little impact on the memory leak issue. Let me try to explain what causes these leaks. Take a look at this code:

    (function outerFunction() {
        var A = 'some variable';
    
       doStuff();
    })();
    

    In the code above, when "outerFunction" finishes "A" goes out of scope and can be garbage collected, freeing that memory.

    What if we add a function in there?

    (function outerFunction() {
        var A = 'some variable';
    
       setTimeout(function(){ alert('I have access to A whether I use it or not'); }, 5);
    })();
    

    In this code (above) the function expression we are passing to setTimeout has a reference to "A" (through the magic of closure) and even after "outerFunction" finishes "A" will remain in memory until the timeout is triggered and the function is dereferenced.

    What if we pass that function to something other than setTimeout?

    (function outerFunction() {
        var A = 'some variable';
    
       doStuff(function(){ alert('I have access to A whether I use it or not'); });
    })();
    
    function doStuff(fn) {
        someElement.onclick = fn;
    }
    

    Now the function expression we are passing to "doStuff" has access to "A" and even after "outerFunction" finishes "A" will remain in memory for as long as there is a reference to the function we passed into doStuff. In this case, we are creating a reference to that function (as an event handler) and therefore "A" will remain in memory until that event handler is cleared. (e.g. someone calls someElement.onclick = null)

    Now look at what happens when we use a function statement:

    (function outerFunction() {
        var A = 'some variable';
    
        function myFunction() { alert('I have also have access to A'); };
        doStuff(myFunction);
    })();
    

    The same problem! "myFunction" will be cleaned up only if "doStuff" does not hold a reference to it and "A" will only be cleaned up when "myFunction" is cleaned up. It does not matter whether we used a statement or an expression; what matters is if a reference to that function is created in "doStuff"!

    0 讨论(0)
  • 2020-12-02 11:47

    Can't we all just get along?

    (function(){
      setTimeout( (function InvokeMe(){ /*some code here*/ }), 5);
    })();
    

    Only one thing really matters, IMO and that's ease of debug. A lot of step tracers won't be able to tell you anything about the func other than the fact that it was anonymous and had args but you can still define inline with a name by putting the definition in parens to force evaluation. For very simple or obvious breaking funcs, I suppose it's not a big deal but to me it's like semis. I really don't care what the other guy does if it doesn't cause pain but I try to always name my funcs because it's not hard and it can be an advantage.

    0 讨论(0)
  • 2020-12-02 11:49

    I prefer to use named functions. Named functions show by name on all debuggers (air, firebug, IE).

    Example:

    Notice that you can also have inline named functions like

    {
        method: function obj_method(){}
    }
    

    This way, when you look at the stack trace, you'll see function obj_method instead of anonymous.

    Were you asking about when to inline a function rather than declare it? When it makes sense in the code. If you need it from two different places, it can't be inline. Sometimes inline make the code easier to read, sometimes harder.

    0 讨论(0)
  • 2020-12-02 11:52

    I suggest a full duel between opposing team members to settle such arguments.

    More seriously, in the end it just doesn't matter. The first form (non-named functions) tends to get unwieldy with larger functions, but isn't a big deal at all with small (1-2 line) functions. The second form is similarly harmless.

    Any argument against either style is pure bikeshedding, imo.

    0 讨论(0)
  • 2020-12-02 11:55

    I think that the only difference in a code like that is that with the second piece of code you can re-call the same function (sometimes with "timer functions" it's useful):

    (function(){
      function invokeMe() {
        if(..) setTimeout(invokeMe, 5);
      }
      setTimeout(invokeMe, 5);
    })();
    
    0 讨论(0)
提交回复
热议问题