JavaScript is a world-beating programming language that can be used for web development, mobile app development (PhoneGap, Appcelerator), server-side development (Node.js and Wakanda), and more. JavaScript is also the first language for many beginners entering the programming world. It can be used both to display simple alert boxes in the browser and to control robots through nodebot or nodruino. Developers who can write well-structured, high-performance JavaScript code have now become the most sought-after people in the job market.
In this article, I will share some JavaScript tips, tricks, and best practices. With a few exceptions, they apply to both browser JavaScript engines and server-side JavaScript interpreters.
The sample code in this article has been tested on the latest version of Google Chrome 30 (V8 3.20.17.15).
1. Always use when assigning a variable for the first timevarkeyword
If a variable is assigned without being declared, it defaults to a new global variable. Try to avoid using global variables.
2. Use===instead of==
==and!=The operator automatically converts data types when necessary. But===and!==don't. They compare both the value and the data type at the same time, which also makes them [faster] than==and!=, 0, false, NaN, and empty strings all evaluate to false in boolean context
[10] === 10 // is false [10] == 10 // is true '10' == 10 // is true '10' === 10 // is false [] == 0 // is true [] === 0 // is false '' == false // is true but true == "a" is false '' === false // is false
3、undefined、null, 0, false, NaN, and empty strings all evaluate to false in boolean context
4. Use semicolons at the end of lines
The truth about semicolons in JavaScript5. Use object constructors。
5. Use object constructors
function Person(firstName, lastName){
this.firstName = firstName;
this.lastName = lastName;
}
var Saad = new Person("Saad", "Mousliki");
6. Be careful withtypeof、instanceofandcontructor
typeofalso returnstypeof null, most object types (Array, Date, etc.) also returnobject: internal prototype property, can be rewritten by codeobjectcontructor: JavaScript operator, searches the constructors in the prototype chain, returns if foundinstanceof, otherwise returnstruefalse
var arr = ["a", "b", "c"]; typeof arr; // 返回 "object" arr instanceof Array // true arr.constructor(); //[]
7. Use self-invoking functions
The function executes automatically immediately after creation, usually called a self-invoked anonymous function or an immediately invoked function expression (IIFE). The format is as follows:
(function(){
// 置于此处的代码将自动执行
})();
(function(a,b){
var result = a+b;
return result;
})(10,20)
8. Randomly get a member from an array
var items = [12, 548 , 'a' , 2 , 5478 , 'foo' , 8852, , 'Doe' , 2145 , 119]; var randomItem = items[Math.floor(Math.random() * items.length)];
9. Get a random number within a specified range
This feature is especially useful when generating fake data for testing, such as salary numbers within a specified range.
var x = Math.floor(Math.random() * (max - min + 1)) + min;
10. Generate an array of numbers from 0 to a specified value
var numbersArray = [] , max = 100; for( var i=1; numbersArray.push(i++) < max;); // numbers = [1,2,3 ... 100]
11. Generate a random alphanumeric string
function generateRandomAlphaNum(len) {
var rdmString = "";
for( ; rdmString.length < len; rdmString += Math.random().toString(36).substr(2));
return rdmString.substr(0, len);
}
12. Shuffle the order of a numeric array
var numbers = [5, 458 , 120 , -215 , 228 , 400 , 122205, -85411];
numbers = numbers.sort(function(){ return Math.random() - 0.5});
/* numbers 数组将类似于 [120, 5, 228, -215, 400, 458, -85411, 122205] */
Here the JavaScript built-in array sorting function is used. A better way is to use dedicated code (such as the Fisher-Yates algorithm). See the discussion on StackOverflowthis discussion。
13. Trim spaces from a string
Java, C#, PHP and other languages all have dedicated string trimming functions, but JavaScript does not. You can use the following code to add forStringthe object atrimfunction:
String.prototype.trim = function(){return this.replace(/^\s+|\s+$/g, "");};
New JavaScript engines already havetrim()native implementations of.
14. Append between arrays
var array1 = [12 , "foo" , {name "Joe"} , -2458];
var array2 = ["Doe" , 555 , 100];
Array.prototype.push.apply(array1, array2);
/* array1 值为 [12 , "foo" , {name "Joe"} , -2458 , "Doe" , 555 , 100] */
15. Convert an object to an array
var argArray = Array.prototype.slice.call(arguments);
16. Verify whether it is a number
function isNumber(n){
return !isNaN(parseFloat(n)) && isFinite(n);
}
17. Verify whether it is an array
function isArray(obj){
return Object.prototype.toString.call(obj) === '[object Array]' ;
}
But iftoString()the method has been overridden, it won't work. You can also use the following method:
Array.isArray(obj); // its a new Array method
If frames are not used in the browser, you can also useinstanceof, but if the context is too complex, it may also fail.
var myFrame = document.createElement('iframe');
document.body.appendChild(myFrame);
var myArray = window.frames[window.frames.length-1].Array;
var arr = new myArray(a,b,10); // [a,b,10]
// myArray 的构造器已经丢失,instanceof 的结果将不正常
// 构造器是不能跨 frame 共享的
arr instanceof Array; // false
18. Get the maximum and minimum values in an array
var numbers = [5, 458 , 120 , -215 , 228 , 400 , 122205, -85411]; var maxInNumbers = Math.max.apply(Math, numbers); var minInNumbers = Math.min.apply(Math, numbers);
19. Empty an array
var myArray = [12 , 222 , 1000 ]; myArray.length = 0; // myArray will be equal to [].
20. Do not directly from the arraydeleteorremoveelements
If you directly use on array elementsdelete, it does not actually delete, but sets the element toundefined. To delete array elements, you should usesplice。
Never:
var items = [12, 548 ,'a' , 2 , 5478 , 'foo' , 8852, , 'Doe' ,2154 , 119 ]; items.length; // return 11 delete items[3]; // return true items.length; // return 11 /* items 结果为 [12, 548, "a", undefined × 1, 5478, "foo", 8852, undefined × 1, "Doe", 2154, 119] */
Instead:
var items = [12, 548 ,'a' , 2 , 5478 , 'foo' , 8852, , 'Doe' ,2154 , 119 ]; items.length; // return 11 items.splice(3,1) ; items.length; // return 10 /* items 结果为 [12, 548, "a", 5478, "foo", 8852, undefined × 1, "Doe", 2154, 119]
When deleting object properties, you can usedelete。
21. Uselengthproperty to truncate an array
In the previous example, usinglengththe property emptied the array. You can also use it to truncate the array:
var myArray = [12 , 222 , 1000 , 124 , 98 , 10 ]; myArray.length = 4; // myArray will be equal to [12 , 222 , 1000 , 124].
At the same time, if you make thelengthproperty larger, the array's length will increase, and it will useundefinedto fill in as new elements.lengthis a writable property.
myArray.length = 10; // the new array length is 10 myArray[myArray.length - 1] ; // undefined
22. Use logical AND/OR in conditions
var foo = 10; foo == 10 && doSomething(); // is the same thing as if (foo == 10) doSomething(); foo == 5 || doSomething(); // is the same thing as if (foo != 5) doSomething();
Logical OR can also be used to set default values, such as default values for function parameters.
function doSomething(arg1){
arg1 = arg1 || 10; // arg1 will have 10 as a default value if it’s not already set
}
23. Makemap()function methods loop over data
var squares = [1,2,3,4].map(function (val) {
return val * val;
});
// squares will be equal to [1, 4, 9, 16]
24. Keep a specified number of decimal places
var num =2.443242342; num = num.toFixed(4); // num will be equal to 2.4432
Note thattoFixec()what is returned is a string, not a number.
25. Floating-point calculation issues
0.1 + 0.2 === 0.3 // is false 9007199254740992 + 1 // is equal to 9007199254740992 9007199254740992 + 2 // is equal to 9007199254740994
Why? Because 0.1+0.2 equals 0.30000000000000004. JavaScript numbers are built according to the IEEE 754 standard, and internally are all 64-bit floating-point representations. For details, seeHow numbers are encoded in JavaScript.
You can usetoFixed()andtoPrecision()to solve this problem.
26. Check object properties with a for-in loop
The following usage can prevent iteration from entering the object's prototype properties.
for (var name in object) {
if (object.hasOwnProperty(name)) {
// do something with name
}
}
27. Comma operator
var a = 0; var b = ( a++, 99 ); console.log(a); // a will be equal to 1 console.log(b); // b is equal to 99
28. Temporarily store variables for calculation and lookup
In jQuery selectors, you can temporarily store entire DOM elements.
var navright = document.querySelector('#right');
var navleft = document.querySelector('#left');
var navup = document.querySelector('#up');
var navdown = document.querySelector('#down');
29. Check incoming in advanceisFinite()parameters
isFinite(0/0) ; // false
isFinite("foo"); // false
isFinite("10"); // true
isFinite(10); // true
isFinite(undefined); // false
isFinite(); // false
isFinite(null); // true,这点当特别注意
30. Avoid using negative numbers as indices in arrays
var numbersArray = [1,2,3,4,5];
var from = numbersArray.indexOf("foo") ; // from is equal to -1
numbersArray.splice(from,2); // will return [5]
Note that the index parameter passed tosplicemust not be negative; when it is negative, elements will be deleted from the end of the array.
31. Use JSON for serialization and deserialization
var person = {name :'Saad', age : 26, department : {ID : 15, name : "R&D"} };
var stringFromPerson = JSON.stringify(person);
/* stringFromPerson 结果为 "{"name":"Saad","age":26,"department":{"ID":15,"name":"R&D"}}" */
var personFromString = JSON.parse(stringFromPerson);
/* personFromString 的值与 person 对象相同 */
32. Do not useeval()or function constructors
eval()and the function constructor (Functionconsturctor) have significant overhead; every time they are called, the JavaScript engine has to convert the source code into executable code.
var func1 = new Function(functionCode); var func2 = eval(functionCode);
33. Avoid usingwith()
Usingwith()can add variables to the global scope, so if there are other variables with the same name, it will cause confusion and the values will also be overwritten.
34. Do not use for-in on arrays
Avoid:
var sum = 0;
for (var i in arrayNumbers) {
sum += arrayNumbers[i];
}
Instead:
var sum = 0;
for (var i = 0, len = arrayNumbers.length; i < len; i++) {
sum += arrayNumbers[i];
}
Another benefit is that,iandlenthe two variables areforin the first declaration of the loop, and both are initialized only once, which is faster than the following approach:
for (var i = 0; i < arrayNumbers.length; i++)
35. Pass tosetInterval()andsetTimeout()use a function instead of a string when
If you passsetTimeout()andsetInterval()a string, they will use a method similar toevalto convert it, which will certainly be slower, so do not use:
setInterval('doSomethingPeriodically()', 1000);
setTimeout('doSomethingAfterFiveSeconds()', 5000);
Instead use:
setInterval(doSomethingPeriodically, 1000); setTimeout(doSomethingAfterFiveSeconds, 5000);
36. Useswitch/caseinstead of a big stack ofif/else
When the condition has more than two branches, useswitch/caseit is faster, more elegant, and better for code organization. Of course, if there are more than 10 branches, do not useswitch/caseit.
37. Inswitch/caseuse numeric ranges in
In fact,switch/casein thecasecondition, it can also be written like this:
function getCategory(age) {
var category = "";
switch (true) {
case isNaN(age):
category = "not an age";
break;
case (age >= 50):
category = "Old";
break;
case (age <= 20):
category = "Baby";
break;
default:
category = "Young";
break;
};
return category;
}
getCategory(5); // 将返回 "Baby"
38. Use an object as the prototype of another object
In the following way, a given object can be passed as a parameter to create a new object with it as its prototype:
function clone(object) {
function OneShotConstructor(){};
OneShotConstructor.prototype = object;
return new OneShotConstructor();
}
clone(Array).prototype ; // []
39. HTML field conversion functions
function escapeHTML(text) {
var replacements= {"<": "<", ">": ">","&": "&", "\"": """};
return text.replace(/[<>&"]/g, function(character) {
return replacements[character];
});
}
40. Do not use try-catch-finally inside loops
In try-catch-finally, the catch part assigns the exception to a variable during execution, and this variable is constructed as a new variable within the runtime scope.
Avoid:
var object = ['foo', 'bar'], i;
for (i = 0, len = object.length; i <len; i++) {
try {
// do something that throws an exception
}
catch (e) {
// handle exception
}
}
Instead:
var object = ['foo', 'bar'], i;
try {
for (i = 0, len = object.length; i <len; i++) {
// do something that throws an exception
}
}
catch (e) {
// handle exception
}
41. Be careful to set a timeout when using XMLHttpRequests
When XMLHttpRequests are executing and have no response for a long time (such as when network problems occur), the connection should be aborted. This can be done throughsetTimeout()to accomplish this:
var xhr = new XMLHttpRequest ();
xhr.onreadystatechange = function () {
if (this.readyState == 4) {
clearTimeout(timeout);
// do something with response data
}
}
var timeout = setTimeout( function () {
xhr.abort(); // call error callback
}, 60*1000 /* timeout after a minute */ );
xhr.open('GET', url, true);
xhr.send();
Also note that you should not initiate multiple XMLHttpRequests at the same time.
42. Handle WebSocket timeouts
Normally, after a WebSocket connection is created, if there is no activity within 30 seconds, the server will time out the connection, and firewalls can also time out connections that have no activity within a unit period.
To prevent this from happening, you can send an empty message to the server at regular intervals. This can be achieved with the following two functions: one to keep the connection alive, and the other specifically to end this state.
var timerID = 0;
function keepAlive() {
var timeout = 15000;
if (webSocket.readyState == webSocket.OPEN) {
webSocket.send('');
}
timerId = setTimeout(keepAlive, timeout);
}
function cancelKeepAlive() {
if (timerId) {
cancelTimeout(timerId);
}
}
keepAlive()The function can be placed at the end of the WebSocket connection'sonOpen()method,cancelKeepAlive()and placed at theonClose()very end of the method.
43. Always note that primitive operators are faster than function calls; use VanillaJS
For example, generally do not do this:
var min = Math.min(a,b); A.push(v);
You can replace it with this:
var min = a < b ? a : b; A[A.length] = v;
44. Pay attention to code structure during development, and check and compress JavaScript code before going live
Don't forget to use a code beautifier when writing code. Use JSLint (a syntax checking tool) and minify the code before going live (for example, using JSMin). Note: UglifyJS is now generally recommended for code minification (https://github.com/mishoo/UglifyJS2)
45. JavaScript is broad and profound; here are some good learning resources
- Code Academy resource: http://www.codecademy.com/tracks/javascript
- Written by Marijn HaverbekeEloquent JavaScript:http://eloquentjavascript.net/
- Written by John ResigAdvanced JavaScript:http://ejohn.org/apps/learn/
Source: http://www.codeceo.com/article/javascript-45-tips.html