This article mainly refers to Appendices A and B of Douglas Crockford’s book Javascript Language Essentials. Mastering them will make the code we write more elegant.

1. Global variables

Javascript global variables, visible in all scopes. It may not be a problem in small programs, and may even be convenient. However, in larger programs, it can become unmanageable and reduce the reliability of the program. The reason for this is that any function can access, modify, and generate global variables internally. If the generated or modified variable has the same name as an existing global variable, they will conflict with each other and even cause the program to fail. In this case, it is often difficult to debug.

There are three ways to define global variables, and we should be careful about inadvertently defining global variables:

  1. In addition to all functions, define a variable with var
  2. Add a property directly to the global object. In the Web browser environment, the global object name is Window.
  3. Use undeclared variables directly (also known as implicit global variables).
<script>
   
    var a = 'Use var to define foo outside of any function';
    window.a2 = 'Add attributes directly to the global object';
    a3 = 'Undeclared variable';
    
    console.log('window.a-->'.window.a);
    console.log('window.a2-->'.window.a2);
    console.log('window.a3-->'.window.a3);
    console.log('window'.window);
    
</script>
Copy the code

2. = =

We all know that Javascript has two sets of equality operators: == and! =, and === and! = =. The difference between the two is that when the former is used to determine whether two values are equal or not, an automatic conversion occurs if the two values are of different types. The conversion rules are complex and hard to remember, and the results are sometimes unexpected. The latter is judged strictly by the two value types, with no automatic conversion. Therefore, it is recommended to use === and! == operator.

console.log(""= ="0"); // false
console.log(0= =""); // true
console.log(0= ="0"); // true

console.log(false= ="false"); // false
console.log(false= ="0"); // true
console.log(false= =undefined); // false

console.log(false= =null); // false
console.log(null= =undefined); // true

console.log("\t\r\n"= =0); // true
Copy the code

3. Plus operator

The plus operator (‘+’) can be used for addition or concatenation of strings. While this design makes Javascript more flexible, it is often a common source of bugs. Therefore, when using, must be careful and careful.

console.log(1 + 1); / / 2
console.log("1" + "0"); / / 10

// If two operation items, one is a string and the other is a number, the number is automatically converted to a string.
alert(1 + "1"); / / 11
Copy the code

4. Automatically insert semicolons at the end of lines

All Javascript statements must end with a semicolon. However, it has a mechanism: it fixes defective programs by automatically inserting semicolons. In other words, when you forget to add a semicolon, instead of reporting an error, the interpreter automatically adds a semicolon for you. However, this mechanism can sometimes lead to errors that are hard to spot. It is recommended that you manually add semicolons after each line of code, rather than relying on this mechanism to add them automatically for you.

The following example leads to unexpected results by returning undefined instead of an object. The reason is that this mechanism inserts semicolons automatically after return statements.

function err() {
    return
      {
        a: 'will return undefined'
      };
}
Copy the code

To avoid this problem, place {at the end of a line.

function err() {
    return {
        a: 'Problem solved'
    };
}
Copy the code

5. NaN

NaN (more on that) means not a number. However, when it is evaluated by typeof, the value is ‘number’.

console.log(typeof NaN);
console.log(typeof NaN= = ='number'); // true
Copy the code

It also has some other strange properties:

NaN= = =NaN; // false
NaN! = =NaN; // true

console.log( 1 + NaN ); // NaN
Copy the code

The above code summed up as:

  • NaN is not equal to all values, including itself.
  • If NaN is an operand in a mathematical operation, the result is NaN

6. Floating point number

Because Javascript follows the binary floating-point arithmetic standard (IEEE 754), and binary floating-point numbers do not properly handle decimal numbers, a weird mathematical problem arises: 0.1 + 0.2 does not equal 0.3. Fortunately, integer arithmetic in floating-point numbers is accurate and can be used to avoid the bugs associated with decimal arithmetic.

console.log( 0.1 + 0.2= = =0.3 ); // false
console.log( ( 0.1 * 10  + 0.2 * 10 ) / 10= = =0.3 ); // true
Copy the code

7. typeof

The typeof operator returns a string that identifies the typeof its operand. Unfortunately, Typeof does not distinguish null from objects, and arrays from objects. This is because, in Javascript, null and arrays are objects.

console.log( typeof null ); // object
console.log( typeof[]);// object
Copy the code
  • Distinguish between NULL and objects
const val = null;

// All objects (including '{}') are true and null is false
if (val && typeof val === 'object') {
    console.log('I'm an object or an array');
} else {
    console.log('I am null');
}
Copy the code
  • Distinguish between arrays and objects

There are many other ways in Javascript to distinguish between arrays and objects, but here are just three.

/ / methods: the Object, the prototype. ToString. Call
const toStr = Object.prototype.toString;
const val = {};
const valType = toStr.call(val);

if (val && typeof val === 'object' && valType === '[object Object]') {
    console.log('I am the object', valType);
} else {
    console.log('I'm an array', valType);
}

IsArray in ES6 is used to determine whether the value passed is an Array
const bool = Array.isArray(val);

if (val && typeof val === 'object' && bool) {
    console.log('I'm an array');
} else {
    console.log('I am the object');
}

// Call constructor to identify it
if (val && typeof val === 'object' && val.constructor === Array) {
    console.log('I'm an Array -- Array');
} else {
    console.log('I'm Object -- Object');
}
Copy the code

8. False value

Javascript has a lot of false values, and if you’re not familiar with them, you can cause unexpected errors in your code.

value type
0 Number
“(empty string) String
false Boolean
null Object
undefined Undefined
NaN (non-numeric) Number

The values above are all equivalent to false, and they are not interchangeable. Also note that undefined and NaN are global variables, not constants, which means you can change their values, but don’t.

9. Wrapper objects of basic types

In Javascript, the three basic data types, numbers, strings, and Booleans, each have corresponding wrapper objects for generating number objects, string objects, and Booleans. Each of these objects has a Valueof method that returns the wrapped value.

const num = new Number(100);
const bool = new Boolean(true);
const str = new String('Hello World');

console.log('Number:' + num.valueOf());
console.log('Boolean value:' + bool.valueOf());
console.log('String:' + str.valueOf());
Copy the code

In real programming, however, they are not very useful and can be confusing. Don’t use them (feel unnecessary and useless). Instead of using new Array and New Object, use [] and {} instead.

10. Statements without blocks

In Javascript, if, for, while, or DO statements can accept not only a block of code enclosed in curly braces, but also a single line of statements. Like this:

if (val) return true;
Copy the code

The advantage of this single-line statement is that you can save two bytes and improve code brevity. However, this benefit has a sting, it is easy to blur the structure of the program, people make mistakes. Here’s an example:

if (val) 
    const bool = true;
    func();
Copy the code

The above code looks like this:

if (val) {
    const bool = true;
    func();
}
Copy the code

But here’s the thing:

if (val) {
    const bool = true;
}
func();
Copy the code

This process of making people think they are doing what they expect when they are actually doing something else is highly unreliable and sometimes difficult to understand. Therefore, for the sake of rigor, it is best to use blocks of code rather than single-line statements.

11. A reserved word

Reserved words in Javascript can be used as key values for object literals, but they must be enclosed in quotes. Also, they can only be expressed in parentheses, not dots.

let obj;

obj = { case: 1 }; / / error
obj = { 'case': 1 }; / / right

obj.case = 2; / / error
obj['case'] = 2; / / right
Copy the code

It is recommended that you do not use any reserved words.

12. parseInt

The parseInt(String, radix) function parses a string and returns an integer. It stops parsing when it encounters a non-number, but does not report an error, so be careful when using it.

console.log(parseInt('10'.10) = = =parseInt('10w'.10)); / / 10
console.log(parseInt('w10'.10)); // NaN
Copy the code

ParseInt (String, radix) The second argument (optional) in the function, indicating the radix of the number to be parsed. It specifies which base parseInt should use when parsing a string. Because older browsers default to base octal when a string starts at ‘0’, ECMAScript 5 defaults to base decimal. In octal, neither 8 nor 9 are numbers, and when parseInt(’08’) or parseInt(’09’) is used to parse time and date, the result is 0. Therefore, it is strongly recommended that you always provide the cardinality.

For details on the use of parseInt, you can click on the details.

13. Eval and with statements

For eval and with statements, the former can easily be tampered with after use to run malicious code that can be attacked, while the latter can be a source of confusing errors and compatibility problems. Therefore, never apply them in your code. But the necessary understanding is needed.

  • The eval details
  • With the details