JavaScript is the world’s leading programming language for Web development, mobile application development (PhoneGap, Appcelerator), server-side development (Node.js, Wakanda), and more. JavaScript is also the first language for many newcomers to the programming world. It can be used to display a simple prompt box in the browser, or to control the robot through NodeBot or Nodruino. Developers who can write well-structured, high-performance JavaScript code are now the most sought after people in the job market.

In this article, I’m going to share a few JavaScript tips, secrets, and best practices that, with a few exceptions, apply to both the browser’s JavaScript engine and the server-side JavaScript interpreter.

The sample code in this article has been tested on the latest version of Google Chrome 30 (V8 3.20.17.15).

1. Use the var keyword when assigning a value to a variable for the first time. If a variable is assigned directly without a declaration, it will be a new global variable by default.

2. Use === instead of == == and! The = operator automatically converts data types if needed. But = = = and! == does not, they compare values and data types at the same time, which also makes them better than == and! = fast.

[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
Copy the code

3. The logical results of underpay, NULL, 0, false, NaN and empty strings are all false

Use semicolons at the end of lines. As a matter of practice, it’s best to use semicolons if you forget to write them. In most cases, the JavaScript interpreter adds them automatically. For details on why to use semicolons, see the JavaScript article the truth about semicolons.

5. Use object constructors

function Person(firstName, lastName){
    this.firstName =  firstName;
    this.lastName = lastName;
}
var Saad = new Person("Saad", "Mousliki");
Copy the code

Use typeof, Instanceof, and Contructor Typeof carefully: Note that typeof NULL also returns object. Most object types (Array, Date, etc.) also return object contructor: The internal stereotype property, which can be overridden by the instanceof: JavaScript operator, will be searched in the constructor in the stereotype chain, returning true if found, false otherwise

var arr = ["a", "b", "c"]; typeof arr; Constructor (); // Return "object" arr instanceof Array. / / []Copy the code

Functions are executed automatically after they are created. The law is usually referred to as the self-invoked Anonymous Function or the Immediately Invoked Function Expression. The format is as follows:

(function(){// The code placed here will execute automatically})(); (function(a,b){ var result = a+b; return result; }) (10, 20)Copy the code

Get a random member from the array

var items = [12, 548 , 'a' , 2 , 5478 , 'foo' , 8852, , 'Doe' , 2145 , 119];
var  randomItem = items[Math.floor(Math.random() * items.length)];
Copy the code

9. Get a range of random numbers This feature is particularly useful in generating dummy data for testing, such as the range of values and salaries.

var x = Math.floor(Math.random() * (max - min + 1)) + min;
Copy the code

Generates an array of numbers from 0 to the specified value

var numbersArray = [] , max = 100;
for( var i=1; numbersArray.push(i++) < max;);  // numbers = [1,2,3 ... 100]
Copy the code

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);
}
Copy the code

12. Shuffle numeric arrays

var numbers = [5, 458 , 120 , -215 , 228 , 400 , 122205, -85411]; Numbers = number.sort (function(){return math.random () -0.5}); /* The numbers array will look like [120, 5, 228, -215, 400, 458, -85411, 122205] */Copy the code

This uses JavaScript’s built-in array sorting functions, better done in specialized code (such as the Fisher-Yates algorithm), as discussed on StackOverFlow.

Java, C#, PHP, and other languages have a String whitespace function, but JavaScript does not have one. You can use the following code to trim the String function:

String.prototype.trim = function(){return this.replace(/^\s+|\s+$/g, ""); };Copy the code

The new JavaScript engine already has a native implementation of trim().

Append between arrays

var array1 = [12 , "foo" , {name "Joe"} , -2458]; var array2 = ["Doe" , 555 , 100]; Array.prototype.push.apply(array1, array2); /* Array1 values [12, "foo", {name "Joe"}, -2458, "Doe", 555, 100] */Copy the code

15. Convert objects to arrays

var argArray = Array.prototype.slice.call(arguments);
Copy the code

16. Verify whether it is a number

function isNumber(n){ return ! isNaN(parseFloat(n)) && isFinite(n); }Copy the code

17. Verify whether it is an array

function isArray(obj){
    return Object.prototype.toString.call(obj) === '[object Array]' ;
}
Copy the code

But if the toString() method is overwritten, it won’t work. You can also use the following methods:

Array.isArray(obj); // its a new Array method
Copy the code

If you don’t have frame in your browser, you can use Instanceof, but if the context is too complex, you can get it wrong.

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 constructor is missing, instanceof result will not be normal // constructor is not shareable across frame arr instanceof Array; // falseCopy the code

Get the maximum and minimum values in the 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);
Copy the code

19. Empty the array

var myArray = [12 , 222 , 1000 ];  
myArray.length = 0; // myArray will be equal to [].
Copy the code

Do not delete or remove elements directly from an array

If you use delete directly on an array element, you are not actually deleting it, just setting the element to undefined. Array elements should be removed using splice. Avoid by all means:

var items = [12, 548 ,'a' , 2 , 5478 , 'foo' , 8852, , 'Doe' ,2154 , 119 ]; items.length; // return 11 delete items[3]; // return true items.length; [12, 548, "a", undefined × 1, 5478, "foo", 8852, undefined × 1, "Doe", 2154, 119] */Copy the code

But should be:

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]Copy the code

You can use delete to delete attributes of an object. We used the length property to empty an array in the previous example. We can also use it to truncate an array:

var myArray = [12 , 222 , 1000 , 124 , 98 , 10 ];  
myArray.length = 4; // myArray will be equal to [12 , 222 , 1000 , 124].
Copy the code

At the same time, if the length property is larger, the array length value will be increased, and undefined will be used to fill in the new element. Length is a writable attribute.

myArray.length = 10; // the new array length is 10
myArray[myArray.length - 1] ; // undefined
Copy the code

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();Copy the code

Logic may also be used to set default values, such as those for function arguments.

function doSomething(arg1){ arg1 = arg1 || 10; Arg1 will have 10 as a default value if it's not already set}Copy the code

Make the map() function method loop over the data

Var squares = [1,2,3,4]. }); // squares will be equal to [1, 4, 9, 16]Copy the code

24, retain the specified decimal number

Var num = 2.443242342; num = num.toFixed(4); // num will be equal to 2.4432Copy the code

Note that toFixec() returns a string, not a number.

Floating point calculation problems

0.1 + 0.2 === 0.3 // is false 9007199254740992 + 1 // is equal to 9007199254740992 + 2 // is equal to to 9007199254740992 9007199254740994Copy the code

Why is that? Because 0.1+0.2 equals 0.30000000000000004. JavaScript numbers are built to the IEEE 754 standard and are internally represented as 64-bit floating-point decimals, see how numbers are encoded in JavaScript. You can fix this by using toFixed() and toPrecision().

26. Check the properties of the object through a for-in loop

The following uses prevent iteration into the object’s stereotype properties.

for (var name in object) {  
    if (object.hasOwnProperty(name)) {
        // do something with name
    }  
}
Copy the code

27. The 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
Copy the code

In the jQuery selector, 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');
Copy the code

29. Check the parameters passed in isFinite() in advance

isFinite(0/0) ; // false isFinite("foo"); // false isFinite("10"); // true isFinite(10); // true isFinite(undefined); // false isFinite(); // false isFinite(null); // trueCopy the code

Avoid using negative numbers as indexes 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]Copy the code

Note that the index parameter passed to Splice should not be a negative number, because negative numbers remove elements from the end of the array.

Serialization and deserialization with JSON

var person = {name :'Saad', age : 26, department : {ID : 15, name : "R&D"} }; var stringFromPerson = JSON.stringify(person); / * stringFromPerson result to "{" name" : "Saad", "age" : 26, "department" : {" ID ": 15," name ":" R&D "}} "* / var personFromString = JSON.parse(stringFromPerson); /* personFromString has the same value as the person object */Copy the code

Don’t use Eval () or Function constructors Eval () and Function consturctor are expensive, and the JavaScript engine has to convert the source code into executable code every time it is called.

var func1 = new Function(functionCode);
var func2 = eval(functionCode);
Copy the code

33, Avoid using with()

Use with() to add variables to the global scope, so that if there are other variables with the same name, they can be confused and the value can be overwritten.

34, Do not use for-in on arrays to avoid:

var sum = 0;  
for (var i in arrayNumbers) {  
    sum += arrayNumbers[i];  
}
Copy the code

But:

var sum = 0;  
for (var i = 0, len = arrayNumbers.length; i < len; i++) {  
    sum += arrayNumbers[i];  
}
Copy the code

Another benefit is that the I and len variables are initialized only once in the first declaration of the for loop, which is faster than writing:

for (var i = 0; i < arrayNumbers.length; i++)
Copy the code

If you pass setTimeout() and setInterval() a string, they will be converted in an eval-like manner, which is definitely slower, so don’t use:

setInterval('doSomethingPeriodically()', 1000);  
setTimeout('doSomethingAfterFiveSeconds()', 5000);
Copy the code

But with:

setInterval(doSomethingPeriodically, 1000);  
setTimeout(doSomethingAfterFiveSeconds, 5000);
Copy the code

Use switch/ Case instead of a stack of if/else when there are more than two branches it is faster, more elegant and easier to organize your code. Of course, if there are more than 10 branches, do not use Switch /case.

Switch /case; switch/case; switch/case

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); // will return "Baby"Copy the code

We can create a new object based on an object given an object as a parameter:

function clone(object) { function OneShotConstructor(){}; OneShotConstructor.prototype = object; return new OneShotConstructor(); } clone(Array).prototype ; / / []Copy the code

HTML field conversion function

function escapeHTML(text) {  
    var replacements= {"<": "<", ">": ">","&": "&", "\"": """};                      
    return text.replace(/[<>&"]/g, function(character) {  
        return replacements[character];  
    });
}
Copy the code

40. Do not use try-catch-finally inside a loop. The catch part of the try-catch-finally assigns an exception to a variable that is constructed into a new variable in the run-time scope.

Avoid by all means:

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  
    }
}
Copy the code

And should be:

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  
}
Copy the code

XMLHttpRequests should terminate the connection if there is no response for a long time (such as network problems). This can be done by using setTimeout() :

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();
Copy the code

It is also important not to make multiple XMLHttpRequests requests at the same time.

Generally, if there is no activity for 30 seconds after a WebSocket connection is created, the server will time out the connection. The firewall can also time out the connection if there is no activity per period. To prevent this, you can send an empty message to the server at regular intervals. You can implement this requirement with two functions, one for keeping the connection active and the other for ending it.

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); }}Copy the code

The keepAlive() function can be placed at the end of the WebSocket connection’s onOpen() method and cancelKeepAlive() at the end of onClose().

Note that primitive operators are faster than function calls. When using VanillaJS, for example, generally do not:

var min = Math.min(a,b); A.push(v); Var min = a < b? a : b; A[A.length] = v;Copy the code

44, Pay attention to code structure while developing, check and compress JavaScript code before going live. You can use tools such as JSLint or JSMin to check and compress code.

45, JavaScript, extensive and profound, there are some good learning Code Academy resources: www.codecademy.com/tracks/java… Eloquent JavaScript by Marjin Haverbekex: Eloquentjavascript.net/Advanced JavaScript by John Resig: ejohn.org/apps/learn/