简体   繁体   中英

Don't make functions within loops Javascript

I get that there are possibly three hundred of these questions, and I understand why not to. If we were looping saying a regular for loop, each iteration we are creating an anonymous function expression which is using more memory. Instead we take the function outside of the loop thus giving it a name

Anonymous Function Iteration Example

var elements = document.getElementsByClassName('elementName');
for(var i=0; i < elements.length; i++ )
{
  elements[i].addEventListener('click',function(e){
    console.log(e);
  });
}

Named Function Iteration Example

function handleClickEvents(e) {
   console.log(e);
}

var elements = document.getElementsByClassName('elementName');
for(var i=0; i < elements.length; i++ )
{
  elements[i].addEventListener('click',handleClickEvents);
}

Problem here is trying to prove someone the logic of this, and to be honest my jsperfs are disproving me completely. Please see the test results for yourself here

So is jsPerf just wrong in the calculations or is this just a myth busted completely? I see that by running the anonymous function as my eventListener function I gain speed compared to the ladder.

Can anyone enlighten me to what the deal is here and why if we gain more speed with the first example should I even bother with two more lines from the second version?

I believe there is flaw in your comparison. If you were to reverse the code. Putting the anonymous function later of the comparison. It will be slower. ( http://jsperf.com/best-event-listener-practice/5 ). Later code will always be slower because there has been so many binding has done before.

You should not worry about performance-- I hardly imagine you are adding millions of event listeners.

The second alternative (specifying a function reference) is superior in that the function, once defined, could potentially be used in other places. It requires fewer }); , and so is less prone to typos. Perhaps more importantly, it is potentially more readable. Let's take the example of passing a function to Array#filter , to check that a filename is a jpg:

names.filter(function(name) { 
    return /\.jpg$/i.test(name);
});

vs.

function isJpeg(name) { return /\.jpg$/i.test(name); }

names.filter(isJpeg);

If you're chaining methods together, the benefits become more obvious:

names . filter(isJpeg) . map(makeThumbnail) . forEach(uploadJpg);

At the end of the day it doesn't really matter and boils down to personal preference, but the one thing that is clear is that performance concerns should not be what drives your decision, except in very specialized situations. A good general rule is to write very short, one-off functions in-line. With ES6 and arrow functions, more functions can be "very short" and be candidates for inlining.

By the way, even when writing the function in-line, it's often a good idea to give it a name:

names.filter(function isJpeg(name) { 

That has a couple of benefits. First, it's a form of documentation/comment and helps people read your code. Second, most debuggers and stack traces will do a better job of reporting about the function. Most minifiers will remove the name so there's no production impact.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM