I. Maintainability Optimization
1. Add Comments
Comments can enhance code readability and maintainability. Of course, the ideal situation is full of comments, but this is not very realistic. So we only need to add comments in some key places:
-
Functions and methods: Especially return values, because they can't be seen directly
-
Large blocks of code (functional modules): Explain module functionality
-
Complex algorithms: Write out key points for easy understanding
-
Hacks: Explain what problem was fixed, whether the current solution is complete, and whether it can be improved
2. "Hint" Variable Types
Hint through initial values, for example:
var found = false;
var count = 1;
var name = '';
var student = null;
3. Decoupling (Layering)
-
Structure layer: HTML
-
Behavior layer: JS
-
Presentation layer: CSS
Try not to "overstep authority". If you really want to overstep, you should also explain with documentation or comments. Try not to have tight coupling, for example:
-
JS-HTML:
elem.innerHTML = '<div class="block"><h2>title</h2><p>content</p></div>'; //Better to replace with the following method (show hidden elements in page) //elem.style.display = 'block'; -
JS-CSS:
elem.style.color = '#e0e0e0'; //Better to replace with the following method (set class, don't set style directly) //elem.className = 'my_class'; -
JS-JS:
//Logic coupling elem.onclick = function(e){ if(txt.value !== null && txt.value !== '' &&...){ //DOM operation } } //Better to replace with the following method (separate logic functional blocks) function isValid(){ return txt.value !== null && txt.value !== '' &&...; } function display(){ //DOM operation } elem.onclick = function(e){ if(isValid()){ display(); } }Several principles to avoid logic coupling:
-
Don't pass event object, only pass needed data
-
Triggering event should not be the only way to execute action
-
Event handlers should only process event-related data (get event source, coordinate values, etc.), then hand over processing to application logic
-
4. Coding Principles
-
Respect object ownership, don't casually modify others' objects, specific requirements:
-
Don't add properties or methods to instances/prototypes
-
Don't rewrite existing methods
Optional solutions:
-
Composition: Create new objects that implement required functionality, reference needed objects
-
Inheritance: Create custom types, inherit from types that need modification, then add extra functionality
-
-
Use namespaces to avoid global variables, for example:
var mySystem = {}; mySystem.mod1 = {...}; -
Use constants to improve maintainability, for example:
var Consts = {}; Consts.IMG_PATH = '../imgs/';Note: Constants include commonly used CSS class names and any other values that may affect maintenance
II. Performance Optimization
1. Avoid Long Scope Chain Lookup
Save frequently referenced global variables as local variables
2. Try Not to Use with Statement
with statement extends scope, there's overhead of long scope lookup, can use saving as local variable instead (not as convenient as with, but somewhat better)
3. Avoid Unnecessary Property Lookup
-
Try to save repeatedly used values as local variables, for example:
//Don't use the following code (6 property lookups) var qs = window.location.href.substring(window.location.href.indexOf('?')); //Should use the following code (4, and more readable) var url = window.location.href; var qs = url.substring(url.indexOf('?')); -
Optimize loops
-
Decrement iteration is faster (i--)
-
Simplify termination condition, termination condition is checked every loop iteration, simplifying condition improves efficiency
-
Simplify loop body, minimize calculations inside loop body as much as possible
-
Use post-test loop (do...while), can avoid judgment before first loop
-
-
Unroll loops
If loop count is determined, best not to use loop, because loop has extra overhead of creating loop and handling termination conditions, for example:
for(i = 0;i < 2;i++){
process(arr[i]);
}
//Following is faster than above
process(arr[0]);
process(arr[1]);
process(arr[2]);
If loop count cannot be determined, can use Duff's device (invented by Tom Duff) to unroll part of loop, improve efficiency, for example:
//credit: Jeff Greenberg for JS implementation of Duff's Device
//Assume values.length > 0
var iterations = Math.ceil(values.length / 8);
var startAt = values.length % 8;
var i = 0;
do {
switch(startAt){
case 0: process(values[i++]);
case 7: process(values[i++]);
case 6: process(values[i++]);
case 5: process(values[i++]);
case 4: process(values[i++]);
case 3: process(values[i++]);
case 2: process(values[i++]);
case 1: process(values[i++]);
}
startAt = 0;
} while (--iterations > 0);
//Above code from: http://www.cnblogs.com/kylindai/archive/2013/12/04/3458476.html
Or another faster Duff's method:
//credit: Speed Up Your Site (New Riders, 2003)
var iterations = Math.floor(values.length / 8);
var leftover = values.length % 8;
var i = 0;
if (leftover > 0){
do {
process(values[i++]);
} while (--leftover > 0);
}
do {
process(values[i++]);
process(values[i++]);
process(values[i++]);
process(values[i++]);
process(values[i++]);
process(values[i++]);
process(values[i++]);
process(values[i++]);
} while (--iterations > 0);
//Above code from: http://www.cnblogs.com/kylindai/archive/2013/12/04/3458476.html
4. Avoid double interpretation
Double interpretation means: using JS to parse JS. Specifically using eval() function or new Function(strCode) or setTimeout(strCode)
Disadvantages of double interpretation: Need to start another parser to parse, there's significant overhead, much slower than direct parsing
- Native methods are faster
Native methods are modules compiled with C/C++, so much faster
- switch is faster than if-else
Reason is hard to say, can refer to CSDN
- Bitwise operations are not faster
In other languages simplifying mathematical operations to bitwise operations can improve calculation speed, but no such thing in JS, because JS internally only has one numeric type (double), so doing bitwise operations needs折腾: double - int - do bitwise operation - double, performance can be imagined
-
Reduce statement count
-
Use 1 var to declare multiple variables
-
Insert iterative values, arr[i++] one statement handles it, no need to make i++ independent statement
-
Use array/object literals, code lines obviously become fewer
-
-
DOM optimization
-
Reduce live updates, can use DocumentFragment to optimize
-
Using innerHTML to create DOM nodes is faster than creating a bunch of nodes then assembling, but exists JS-HTML coupling problem, consider carefully
-
Use event delegation
-
Note real-time updating collections (NodeList, NamedNodeMap, HTMLCollection)
Besides saving reference as local variable, also note accessing its properties also needs re-query, for example: var imgs = document.images; accessing imgs.length also needs to query again
-
III. Deployment Optimization
-
Use validation tools (such as JSLint) to check code, discover potential problems beyond syntax errors
-
Remove comments (for security considerations)
-
Merge js files, minimize number of external files
-
Compress code (such as YUI compressor), reduce code size itself, can also obfuscate code simultaneously, improve security, but obfuscating code itself has risks, may trigger errors
-
Enable server compression functionality, such as gzip module
No comments yet. Be the first to share your thoughts.