Home  >  Article  >  Web Front-end  >  In-depth exploration of the efficiency issues and related optimization of for loops in JavaScript_javascript skills

In-depth exploration of the efficiency issues and related optimization of for loops in JavaScript_javascript skills

WBOY
WBOYOriginal
2016-05-16 15:10:521542browse

Underscore.js library

How many loops have you written in one day (week)?

var i;
for(i = 0; i < someArray.length; i++) {
 var someThing = someArray[i];
 doSomeWorkOn(someThing);
}

It's harmless, of course, but it's ugly and weird and not really something to complain about. But this way of writing is too banal.

var i,
 j;
for(i = 0; i < someArray.length; i++) {
 var someThing = someArray[i];
 for(j = 0; j < someThing.stuff.length; j++) {
   doSomeWorkOn(someThing.stuff[j]);
 }
}

You're extending bad code, and before you throw a bunch of ifs, you're already insane.
I haven't written a loop in two years.
"What are you talking about?"
It's true, a bad joke. Actually not none (ok, I did write a few), because I don’t write loops and my code is easier to understand.
How?

_.each(someArray, function(someThing) {
 doSomeWorkOn(someThing);
})

Or better yet:

_.each(someArray, doSomeWorkOn);

This is what underscorejs does. Clean, simple, readable, short, no intermediate variables, no tons of semicolons, simple and very elegant.
Here are some more examples.

var i,
 result = [];
for(i = 0; i < someArray.length; i++) {
 var someThing = someArray[i];
 // 打到这,我已经手疼了
 if(someThing.isAwesome === true) {
   result.push(someArray[i]);
 }
}

Again, a typical use case for wasting time using loops. Even though these sites promote anti-smoking and vegetarianism, I feel outraged when I see these codes. Look at the simple way to write it.

var result = _.filter(someArray, function(someThing) {
 return someThing.isAwesome === true;
})

Like the name of filter in underscore, just 3 lines of code can give you a new array.
Or do you want to convert these arrays into another form?

var result = _.map(someArray, function(someThing) {
 return trasformTheThing(someThing);
})

The above three examples are sufficient in daily life, but these functions are not enough for underscore to be put on the table.

var grandTotal = 0,
 somePercentage = 1.07,
 severalNumbers = [33, 54, 42],
 i; // don't forget to hoist those indices;
for(i = 0; i < severalNumbers.length; i++) {
 var aNumber = severalNumbers[i];
 grandTotal += aNumber * somePercentage;
}

underscore version

var somePercentage = 1.07,
 severalNumbers = [33, 54, 42],
 grandTotal;
grandTotal = _.reduce(severalNumbers, function(runningTotal, aNumber) {
 return runningTotal + (aNumber * somePercentage);
}, 0)

This may seem a bit strange at first. I checked the documentation about reduce and found out about its existence. Since I refuse to use loops, it's my first choice. The above things are just an introduction. The underscorejs library also has a lot of awesome functions.

30 days no use cycle challenge.

Don’t use any loops for the next 30 days. If you see a bunch of nasty and rough stuff, replace them with each or map. Use a little more reducing.

You need to note that Underscore is the gateway to functional programming. A visible, invisible way. A good way to go.


OurJS Note* Modern browsers currently support each, filter, map, and reduce methods, but the underscore library can achieve compatibility with older versions of IE. The following is an example written using ES5 native methods:

[3,4,5,3,3].forEach(function(obj){
  console.log(obj);
});

[1,2,3,4,5].filter(function(obj){
  return obj < 3
});

[9,8,5,2,3,4,5].map(function(obj){
  return obj + 2;
});

[1,2,3,4,5].reduce(function(pre, cur, idx, arr) {
  console.log(idx);  //4 个循环: 2-5
  return pre + cur;
});  //15

//sort方法同样很有用
[9,8,5,2,3,4,5].sort(function(obj1, obj2){
  return obj1 - obj2;
});

for in and for loop

Someone pointed out that the efficiency of for in is much lower than that of for loop. Now let's test the efficiency of using for in, for loop and forEach in different browsers when processing large arrays.

At present, most open source software will cache the array length in the for loop, because the common view is that some browsers Array.length will recalculate the array length every time, so temporary variables are usually used to store the array length in advance, such as:

for (var idx = 0, len = testArray.length; idx < len; idx++) {
 //do sth.
}

We will also test the performance difference between caching and no caching.

Also add a summation operation in each test loop to show that it is not an empty loop.

for (var idx = 0, len = testArray.length; idx < len; idx++) {
 //do sth.
}

We will also test the performance difference between caching and no caching.

Also add a summation operation in each test loop to show that it is not an empty loop.

The test code is as follows, click Run to view
HTML code

<h4 id="browser"></h4>
<table id="results" class="table"></table>

JavaScript code

function () {

 //准备测试数据, 有200万条数据的大数组
 var testArray = []
  , testObject = {}
  , idx
  , len = 2000000
  , tmp = 0
  , $results = $("#results")
  , $browser = $("#browser")
  ;

 $browser.html(navigator.userAgent);
 $results.html('');

 for (var i = 0; i < len; i++) {
  var number = Math.random(); //若希望加快运算速度可使用取整:Math.random() * 10 | 0
  testArray.push(number);
  testObject[i] = number;
 }

 $results.append('<tr><th>测试代码</th><th>计算结果</th><th>所需时间,毫秒</th></tr>');

 //测试函数
 var test = function(testFunc) {
  var startTime
   , endTime
   , result
   ;

  startTime = new Date();
  tmp = 0;
  testFunc();
  endTime  = new Date();

  //计算测试用例(Test Case)运行所需要的时间
  result = endTime - startTime;
  $results.append('<tr><td><pre class="brush:php;toolbar:false">{0}
{1}{2}'.format(testFunc.toString(), tmp | 0, result)); }; test(function() { //测试for in 的效率 for (idx in testArray) { tmp += testArray[idx]; //经测试,idx是string类型,可能是慢的原因之一 } }); test(function() { //测试for loop循环的效率 for (idx = 0, len = testArray.length; idx < len; idx++) { tmp += testArray[idx]; } }); test(function() { //测试forEach的效率 testArray.forEach(function(data) { tmp += data; }); }); test(function() { //测试不缓存Array.length时效率 for (idx = 0; idx < testArray.length; idx++) { tmp += testArray[idx]; } }); test(function() { //测试使用{} (Object) 存健值对时,使用for in的效率如何 for (idx in testObject) { tmp += testObject[idx]; } }); test(function() { //测试从{} Object查值时的效率如何(这里的健key值事先己知) for (idx = 0, len = testArray.length; idx < len; idx++) { tmp += testObject[idx]; } }); }

Run [Please wait a moment]
Test results
The test results may vary depending on the calculation. This is a summary of the test results of Firefox, Chrome, and IE running on my machine.

2016313110044207.jpg (971×678)

The following are several observed conclusions

  • For in is much slower than for loop, at least 20 times slower in Chrome
  • FF has optimized forEach (ES5), and its performance is better than for loop, but Chrome/IEn performance is poor
  • FF/Chrome caching Array.length is a little slower than using it directly. Except for the latest version of IE, the performance improvement is minimal (this is very unexpected)
  • In some cases, FF’s JS engine performance seems to be better than V8
Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn