Balancing Code Style and Performance in JavaScript

When writing JavaScript code, what should be our primary concern?

Programs are meant to be read by humans, only occasionally executed by computers. — Donald Ervin Knuth

Should we prioritize coding style or efficiency? In most scenarios where extreme performance isn't required, we should focus on code style and readability to improve maintainability. The balance between style and efficiency depends on the specific use case.

The Left-pad Incident

Let's revisit the controversial left-pad incident from 2016 that sparked widespread discussion in the developer community.

The incidant raised several concerns:

  • NPM module granularity
  • Coding style
  • Code quality/performance

The original implementation looked like this:

function leftpad(originalString, targetLength, paddingChar){
    originalString = String(originalString);
    
    var counter = -1;
    
    if(!paddingChar && paddingChar !== 0) paddingChar = "";
    
    targetLength = targetLength - originalString.length;
    
    while(++counter < targetLength){
        originalString = paddingChar + originalString;
    }
    
    return originalString;
}

While some criticized this code, particularly its performance, it's actually quite readable. The module granularity was a reflection of the ecosystem at the time when tree-shaking capabilities were limited. Today, such fine-grained modules would be considered excessive, but at the time, it was a reasonable approach.

The code style is straightforward and highly readable—good code often serves as its own documentation.

Regarding performance, this implementation has O(N) time complexity. However, in practical usage scenarios, we rarely need to pad extremely long strings, making this approach acceptable for most cases.

Optimization Approach

Let's explore how to optimize this function. Instead of concatenating the padding character N times through a loop, we can leverage binary operations for better performance.

Consider padding the character '*' 100 times. The decimal number 100 is 1100100 in binary. A standard loop would perform 100 iterations, but using binary exponentiation, we can achieve the same result in just 7 iterations.

Here's an optimized version:

function leftpad(originalString, targetLength, paddingChar=""){
    originalString = "" + originalString;

    const requiredPadding = targetLength - originalString.length;
    
    if(requiredPadding <= 0){
        return originalString;
    }else{
        return ("" + paddingChar).repeat(requiredPadding) + originalString;
    }
}

This implementation uses ES6 features like default parameters and the string's repeat method. The key to understanding its efficiency lies in how the repeat method is implemented under the hood.

The polyfill implementation on MDN contains the following critical code:

var repeatedString = ""
for(;;){
    if((paddingCount & 1) == 1) {
        repeatedString += paddingChar;
    }
    
    paddingCount >>>= 1;
    
    if(paddingCount == 0){
        break;
    }
    
    paddingChar += paddingChar;
}

This algorithm uses bitwise operations: the & (AND) operator and the >>> (unsigned right shift) operator. The expression paddingCount & 1 checks the least significant bit of paddingCount, while paddingCount >>>= 1 right-shifts the binary representation by one bit.

The algorithm effectively traverses the binary representation of paddingCount in reverce. With each iteration, paddingChar doubles in length (2^n), and whenever a bit is 1, the current paddingChar is added to the result.

For our example of padding with '*' 100 times (binary 1100100), the algorithm would:

  • Iterate 8 times (7 + 1)
  • Double paddingChar each time: 1*, 2*, 4*, 8*, 16*, 32*, 64*
  • Add to result when bit is 1: 4*, 32*, 64*
  • Result: 4 + 32 + 64 = 100 '*' characters

This approach has O(log N) time complexity, where the number of iterations equals the number of bits in paddingCount.

Interestingly, the MDN polyfill has since reverted to a simpler while loop implementation:

while (paddingCount) {
   paddingChar += paddingChar;
   paddingCount--;
}

This demonstrates that in most scenarios, the performance requirements aren't extreme enough to justify complex optimizations, reinforcing that code style should generally take precedence.

Identity Matrix Example

Consider this code snippet for checking if a matrix is an identity matrix:

function isIdentityMatrix(matrix) {
    if (matrix.length === 0) return false;
    const rows = matrix.length;
    const cols = matrix[0].length;
    
    if (rows !== cols) return false;
    
    for (let i = 0; i < rows; i++) {
        for (let j = 0; j < cols; j++) {
            if (i === j) {
                if (matrix[i][j] !== 1) return false;
            } else {
                if (matrix[i][j] !== 0) return false;
            }
        }
    }
    
    return true;
}

This code has several issues:

  • It's lengthy and moderately readable
  • Limited extensibility
  • Poor encapsulation

However, this represents an actual implementation where performance is prioritized. In scenarios demanding maximum efficiency, such optimizations are justified.

This example illustrates that in real-world development, we must make context-dependent decisions about when to prioritize style versus performance.

Conclusion

We've explored how bitwise operations can implement fast exponentiation to reduce loop iterations and improve code efficiency. However, when performance requirements aren't extreme, code readability should be our primary concern.

The choice between style and efficiency ultimately depends on the specific requierments and constraints of each project.

Tags: javascript code-style performance-optimization bit-manipulation algorithms

Posted on Wed, 22 Jul 2026 17:07:26 +0000 by rachel2004