惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

N
News | PayPal Newsroom
Security Archives - TechRepublic
Security Archives - TechRepublic
Hacker News: Ask HN
Hacker News: Ask HN
H
Hacker News: Front Page
Apple Machine Learning Research
Apple Machine Learning Research
TaoSecurity Blog
TaoSecurity Blog
Help Net Security
Help Net Security
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
V
V2EX
Hugging Face - Blog
Hugging Face - Blog
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
人人都是产品经理
人人都是产品经理
博客园 - 三生石上(FineUI控件)
Security Latest
Security Latest
Cloudbric
Cloudbric
WordPress大学
WordPress大学
S
SegmentFault 最新的问题
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
www.infosecurity-magazine.com
www.infosecurity-magazine.com
Know Your Adversary
Know Your Adversary
A
Arctic Wolf
L
LangChain Blog
Application and Cybersecurity Blog
Application and Cybersecurity Blog
The GitHub Blog
The GitHub Blog
P
Proofpoint News Feed
W
WeLiveSecurity
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
M
MIT News - Artificial intelligence
Google DeepMind News
Google DeepMind News
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
The Cloudflare Blog
小众软件
小众软件
NISL@THU
NISL@THU
云风的 BLOG
云风的 BLOG
P
Privacy & Cybersecurity Law Blog
S
Security @ Cisco Blogs
博客园 - 【当耐特】
I
InfoQ
Vercel News
Vercel News
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
P
Proofpoint News Feed
O
OpenAI News
Google DeepMind News
Google DeepMind News
N
News and Events Feed by Topic
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
K
Kaspersky official blog
T
Threat Research - Cisco Blogs
量子位
宝玉的分享
宝玉的分享

JavaScript iDiallo.com

How to tell an element is in view using JavaScript. Complex function call delays without nesting in JavaScript How to use pushState without breaking the back button How to create DOM elements efficiently with JavaScript Uncaught TypeError: Cannot read property of null Why Use Prototype in JavaScript Uncaught SyntaxError: Unexpected token < Magical JavaScript Live Collection Creating a class in JavaScript
Optimization: Minimize look-ups in for loops.
Ibrahim Dial · 2016-10-28 · via JavaScript iDiallo.com

In JavaScript, like in many other languages a loop can be defined in many ways. The standard of course is the for-loop, the while loop, or do while loop. They are all natively implemented in JavaScript and benefit from the just in time compiler to be optimized for speed. There is recursion too that can be considered a loop, but let's limit ourselves to the native ones.

When I started learning JavaScript, the simplest way to iterate through sets of values was using a for-loop. Here is a simple example of it being used.

// Select elements by class name. This was in 2009 so bear with me
var allElements = document.getElementsByTagName("*");
var elements = new Array();
var className = "selected";

for(var i = 0; i < allElements.length;i++){
    if (allElements[i].className.indexOf(className) != -1 ) {
        elements.push(allElements[i]);
    }
}

console.log(elements); 
// all elements with selected class name.

This worked pretty well. You can wrap it in a function and call it whenever you need to get an element by its class name. However, there are a few things that are redundant.

For each iteration of the loop, we are access a property of the allElements object.

V8 design docs

Most JavaScript engines use a dictionary-like data structure as storage for object properties - each property access requires a dynamic lookup to resolve the property's location in memory. This approach makes accessing properties in JavaScript typically much slower than accessing instance variables in programming languages like Java and Smalltalk.

If I wrote it like this it would be easier to understand: allElements["length"]. When we run our loop, this object property look up happens as many times as the total number of elements. It would be nice if we can do the look up only once and get over it. Well we can.

for (var i = 0, l = allElements.length; i < l; i++)

Now the value of the length property is saved once in a variable l for length, and the condition only has to compares two literals, which is much faster.

Unfortunately, inside our loop there are also other problems. Inside the if statement we are checking if the class name exists, to do so we are using another look up: allElements[i]. And when we meet our condition, we are doing the same look up again to append it to our array. We can fix this in two steps.

First we can save that element in a variable so we don't have to do the look up multiple times.

for (var i = 0, l = allElements.length; i < l; i++) {
    var currentElement = allElements[i];
    if (currentElement.className.indexOf(className) != -1 ) {
        elements.push(currentElement);
    }
}

This is a great improvement and it makes it easier to read. We could call it a day but there is one little thing that isn't quite right. In JavaScript, creating a new variable in a for-loop doesn't add it to a new scope. Instead, the variable is hoisted up to the top of the current scope. For each iteration we are hoisting up a new variable that overwrites the previous one. To fix this, we can declare the variable outside of the loop.

var allElements = document.getElementsByTagName("*"),
    elements = [],
    className = "selected",
    currentElement = null;

for (var i = 0, l = allElements.length; i < l; i++) {
    currentElement = allElements[i];
    if (currentElement.className.indexOf(className) != -1 ) {
        elements.push(currentElement);
    }
}

Note that I also combined the variable declarations. Only one var is used at the top followed by a comma to separate each assignment. Now comes one questions. Optimization or Readability.

We can optimize it some more by moving the second var out of the for-loop since it is going to get hoisted up anyway.

var allElements = document.getElementsByTagName("*"),
    elements = [],
    className = "selected",
    currentElement = null,
    i = 0,
    l = allElements.length;

for (; i < l; i++) {
    currentElement = allElements[i];
    if (currentElement.className.indexOf(className) != -1 ) {
        elements.push(currentElement);
    }
}

But now we get this funky looking for loop: for (; i < l; i++). Although it works just the same and limits the code to do only what it is supposed to do at a slightly faster speed, it might confuse the next developer that has to maintain your code. At points like this, I always choose readability over optimization.


Now that we optimized our loop the question is, was it worth it? How much more speed are we gaining by doing this. The answer is very little. Especially if you are going to run this function only once at a time, the gain is negligible. But, if you are doing something like game programming, or animations, having this sort of mentality will go a long way.

Games usually work using a main loop: A controlled infinite loop that drives the entire game. So in order to obtain the maximum frames per second it's important to make sure your code is not doing anything unnecessary. Removing some extra look ups may help you meet your goals, and hopefully keep the code readable enough so you can always work on it.


Did you like this article? Subscribe for more and follow updates via RSS.

Back to JavaScript articles