This is the 5th day of my participation in the August More Text Challenge

Chapter 3 language Basics (3)

3.4 Data Types

ECMAScript has six simple data types (also known as primitive types) : Undefined, Null, Boolean, Number, String, and Symbol. Symbol is new to ECMAScript 6. There is also a complex data type called Object. Object is an unordered collection of name-value pairs. Because you cannot define your own data types in ECMAScript, all values can be represented by one of the seven data types mentioned above. Having only seven data types seems inadequate to represent all data. But ECMAScript’s data types are flexible, and one data type can be used as multiple data types.

3.4.1 track typeof operator

Because ECMAScript’s type system is loose, you need a way to determine the data type of arbitrary variables. The Typeof operator was created for this purpose. Using the Typeof operator on a value returns one of the following strings:

  • “Undefined” indicates undefined value;
  • “Boolean” indicates that the value is Boolean; (There are only true and false states)
  • “String” indicates that the value is a string;
  • “Number” indicates a numerical value.
  • “Object” indicates that the value is an object (not a function) or null;
  • “Function” means the value is a function;
  • “Symbol” means the value is a symbol.

Here is an example of using the Typeof operator:

let message = "some string";
console.log(typeof message); // "string"
console.log(typeof(message)); // "string"
console.log(typeof 95); // "number"
Copy the code

In this example, we pass a variable (message) and a numeric literal to the Typeof operator. Note that because Typeof is an operator and not a function, no arguments are required (but arguments can be used).

Note that typeof returns results that can be confusing in some cases, but are technically correct. For example, a call to typeofNULL returns “object”. This is because the special value null is considered a reference to an empty object.

3.4.2 Undefined type

Undefined has only one value, which is the special value Undefined. When a variable is declared using var or let but not initialized, it is equivalent to assigning undefined value to the variable:

let message;
console.log(message == undefined); // true
Copy the code

In this example, the variable message is not initialized when it is declared. When you compare it to the literal of undefined, they are equal. This example is equivalent to the following:

let message = undefined;
console.log(message == undefined); // true
Copy the code

Here, the variable message is explicitly initialized with undefined. This is not necessary, because by default, any uninitialized variable takes undefined.

Note that variables that contain undefined are different from undefined variables. Look at the following example:

let message; // let age console.log(message); // Let age console.log(message); // "undefined" console.log(age); / / an errorCopy the code

In the example above, the first console.log will indicate the value of the variable message, which is “undefined”. The second console.log outputs the value of an undeclared variable age, which results in an error. Only one useful operation can be performed on an undeclared variable, which is to call Typeof on it. (Calling delete on an undeclared variable also doesn’t give an error, but it doesn’t help and actually throws an error in strict mode.)

Calling typeof on an uninitialized variable returns “undefined”, but calling it on an undeclared variable returns “undefined”, which is a bit confusing. Take the following example:

let message; // Let age console.log(typeof message); // Let age console.log(typeof message); // "undefined" console.log(typeof age); // "undefined"Copy the code

Whether declared or undeclared, Typeof returns the string “undefined”. This is logically correct, because while strictly speaking these two variables are fundamentally different, neither of them can actually perform operations.

Note that even though uninitialized variables are automatically assigned a undefined value, it is recommended that we initialize them at the same time we declare them. This way, when typeof returns “undefined”, you know that it is because the given variable is undeclared, rather than declared but uninitialized.

Undefined is a false value. Therefore, you can detect it in a more concise way if you need to. Keep in mind, though, that there are many other possible values that are equally false. Be sure you want to check for undefined, not just false values.

let message; If (message) {// This block will not execute} if (! Message) {// This block will execute} if (age) {// there will be an error}Copy the code

Rule 3.4.3 Null type

The Null type also has only one value, the special value Null. Logically, a null value represents an empty object pointer, which is why passing a null to typeof returns “object” :

let car = null;
console.log(typeof car); // "object"
Copy the code

When defining variables that will hold object values in the future, it is recommended to use NULL for initialization and not other values. If the value of the variable is null, you can tell if the variable was later assigned a reference to an object, for example:

if (car ! = null) {// CAR is a reference to an object}Copy the code

Undefined values are derived from null values, so ECMA-262 defines them as ostensibly equal, as shown in the following example:

console.log(null == undefined); // true
Copy the code

Comparing null and undefined with the equal operator (==) always returns true. Note, however, that this operator converts its operands for comparison purposes (more on this later in this chapter).

Even if null is related to undefined, their purpose is completely different. As mentioned earlier, you never have to explicitly set the variable value to undefined. But null doesn’t work like that. Any time a variable wants to hold an object and there is no object available at the time, null is used to fill the variable. This preserves the semantics of null as an empty object pointer and further distinguishes it from undefined.

Null is a false value. Therefore, you can detect it in a more concise way if you need to. Keep in mind, though, that there are many other possible values that are equally false. Be sure that you want to detect null literals, not just false values.

let message = null; let age; If (message) {// This block will not execute} if (! Message) {// This block will execute} if (age) {// this block will not execute} if (! Age) {// This block will execute}Copy the code

3.4.4 Boolean type

The Boolean type is one of the most frequently used types in ECMAScript and has two literals: true and false. These two Booleans are different from numeric values, so true is not equal to 1 and false is not equal to 0. Here is an example of assigning a Boolean value to a variable:

let found = true;
let lost = false;
Copy the code

Note that the Boolean literals true and false are case sensitive, so true and false (and other size mashups) are valid identifiers, but not Booleans.

Although there are only two Booleans, all other ECMAScript type values have corresponding Boolean equivalents. To convert a value of another type to a Boolean, call the special Boolean() transformation function:

let message = "Hello world!" ; let messageAsBoolean = Boolean(message);Copy the code

In this example, the string message is converted to a Boolean value and stored in the variable messageAsBoolean. Boolean() The transformation function can be called on any type of data and always returns a Boolean value. The rules for what values can be converted to true or false depend on the data type and the actual value. The following table summarizes the conversion rules between different types and Booleans.

The data type To a value of true Convert to a value of false
Boolean true false
String Non-empty string “” (empty string)
Number Non-zero values (including infinity) 0. NaN (see related content later)
Object Any object null
Undefined N/A (non-existent) undefined

It is important to understand the above conversions because flow control statements like if automatically perform conversions of other types of values to Booleans, such as:

let message = "Hello world!" ; if (message) { console.log("Value is true"); }Copy the code

In this case, console.log prints the string “Value is true” because the string message is automatically converted to the equivalent Boolean Value true. Because of this automatic transformation, it is important to understand what variables are used in flow control statements. Using objects incorrectly instead of booleans can significantly change the execution flow of an application.

3.4.5 Number type

Perhaps the most interesting data type in ECMAScript is Number. The Number type uses IEEE 754 format to represent integer and floating point values (also called double values in some languages). Different numeric types have different numeric literal formats accordingly.

The most basic numeric literal format is a decimal integer, which can be written directly:

let intNum = 55; / / integerCopy the code

Integers can also be expressed as octal (base 8) or hexadecimal (base 16) literals. For octal literals, the first digit must be zero (0), followed by the corresponding octal digit (values 0 to 7). If the literal contains more digits than it should, the prefix zero is ignored and the following sequence of digits is treated as a decimal number, as shown below:

let octalNum1 = 070; // let octalNum2 = 079; // Invalid octal value, treat as 79 let octalNum3 = 08; // Invalid octal value, treated as 8Copy the code

Octal literals are invalid in strict mode and cause the JavaScript engine to throw syntax errors. To create A hexadecimal literal, you must prefix the real numeric number with 0x (case sensitive), followed by the hexadecimal number (0, 9, and A, F). The hexadecimal number contains both upper and lower case letters. Here are a few examples:

let hexNum1 = 0xA; // let hexNum2 = 0x1f; // Hexadecimal 31Copy the code

Values created using octal and hexadecimal formats are treated as decimal values in all mathematical operations.

Note that positive (+0) and negative (-0) may actually exist because of the way JavaScript holds values. Plus zero and minus zero are considered equal in all cases, and this is a special note.

  1. Floating point value

    To define a floating point value, the value must contain a decimal point, and there must be at least one digit after the decimal point. The decimal point is not necessarily preceded by an integer, but it is recommended. Here are a few examples:

    Let floatNum1 = 1.1; Let floatNum2 = 0.1; let floatNum3 = .1; // Valid, but not recommendedCopy the code

    Because storing floating-point values uses twice as much memory as storing integer values, ECMAScript always tries to convert values to integers. When there are no numbers after the decimal point, the value becomes an integer. Similarly, if the value itself is an integer followed by a 0 (such as 1.0), it will be converted to an integer, as shown in the following example:

    let floatNum1 = 1.; // Let floatNum2 = 10.0; // If the decimal point is followed by zero, it is treated as an integer 10Copy the code

    Floating-point values can be expressed in scientific notation for very large or very small values. Scientific notation is used to represent a number that should be multiplied by a given power of 10. The format of scientific notation in ECMAScript requires that a numeric value (integer or floating point) be followed by an uppercase or lowercase letter E, plus a power of 10 to be multiplied. Such as:

    Let floatNum = 3.125 e7; / / equal to 31250000Copy the code

    In this example, floatNum is equal to 31 250 000, but scientific notation is more concise. This notation is in effect equivalent to saying, “Take 3.125 as the coefficient and multiply it by 10 to the seventh.”

    Scientific notation can also be used to represent very small values, such as 0.000 000 000 000 000 03. This number can be expressed in scientific notation as 3e17. By default, ECMAScript converts floating point values with at least six zeros after the decimal point to scientific notation (for example, 0.000 000 3 is converted to 3E-7).

    Floating-point values are accurate to up to 17 decimal places, but are far less accurate in arithmetic than integers. For example, instead of adding 0.2 to 0.1, you get 0.300 000 000 000 000 04. This tiny rounding error makes it difficult to test specific floating point values. Take the following example:

    If (a + b == 0.3) {// don't do that! The console. The log (" You got 0.3. "); }Copy the code

    This tests whether the sum of the two values equals 0.3. If the two values are 0.05 and 0.25, or 0.15 and 0.15, that’s fine. But if it is 0.1 and 0.2, as mentioned earlier, the test will fail. So never test a particular floating point value.

    Note that the rounding error is due to the USE of IEEE 754 values and is not unique to ECMAScript. Other languages that use the same format also have this problem.

    1. The range of values

    Due to memory limitations, ECMAScript does not support representing all values in the world. The minimum value that ECMAScript can represent is stored in number.min_value, which in most browsers is 5E-324; The maximum value that can be expressed is stored in number. MAX_VALUE, which in most browsers is 1.797 693 134 862 315 7e+308. If a numerical result of a calculation is out of the range that JavaScript can represent, the value is automatically converted to a special Infinity value. Any unrepresented negative numbers are represented by -infinity, and any unrepresented positive numbers are represented by Infinity.

    If the calculation returns positive Infinity or negative Infinity, the value cannot be used in any further calculation. This is because Infinity has no numerical representation that can be computed. To determine if a value isFinite(that is, between the minimum and maximum that JavaScript can represent), use the isFinite() function, as follows:

    let result = Number.MAX_VALUE + Number.MAX_VALUE;
    console.log(isFinite(result)); // false
    Copy the code

    Computations beyond finite values are rare, but they are always possible. Therefore, when calculating very large or very small values, it is necessary to monitor whether the results are out of range.

    NEGATIVE_INFINITY and POSITIVE_INFINITY can also be used to get positive and negative Infinity. Yes, these two properties contain the values -infinity and Infinity, respectively.

  2. NaN

    A special value called NaN, which means “Not a Number,” is used to indicate that an operation that was supposed to return a Number failed (rather than throw an error). For example, dividing 0 by any value in other languages usually results in an error that stops code execution. But in ECMAScript, dividing 0, +0, or -0 returns NaN:

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

    If the numerator is non-zero and the denominator is signed or unsigned 0, Infinity or -infinity is returned:

    console.log(5/0); // Infinity
    console.log(5/-0); // -Infinity
    Copy the code

    NaN has several unique attributes. First, any operation that involves a NaN always returns a NaN (such as NaN/10), which can be a problem in successive multi-step calculations. Second, NaN is not equal to any value including NaN. For example, the following comparison returns false:

    console.log(NaN == NaN); // false
    Copy the code

    For this purpose, ECMAScript provides the isNaN() function. This function takes an argument, which can be of any data type, and determines whether the argument is “not a number.” After passing a value to isNaN(), the function attempts to convert it to a numeric value. Some non-numeric values can be converted directly to numeric values, such as the string “10” or a Boolean value. Any value that cannot be converted to a numeric value causes this function to return true. Examples are as follows:

    console.log(isNaN(NaN)); // true console.log(isNaN(10)); // false, 10 is the value console.log(isNaN("10")); // false, which can be converted to value 10 console.log(isNaN("blue")); // true, can not be converted to numeric console.log(isNaN(true)); // false, which can be converted to the value 1Copy the code

    The above example tests five different values. The first test is NaN itself, which obviously returns true. We then test the value 10 and the string “10”, both returning false because they both have a value of 10. The string “blue” cannot be converted to a numeric value, so the function returns true. The Boolean value true can be converted to the value 1, so it returns false.

    Note that isNaN() can be used to test objects, although it is uncommon. At this point, the valueOf() method of the object is called first, and then the returned value can be converted to a numeric value. If not, call the toString() method again and test its return value. This is typically how ECMAScript built-in functions and operators work, as discussed later in this chapter.

  3. Numerical transformation

    There are three functions to convert non-numeric values to numeric values: Number(), parseInt(), and parseFloat(). Number() is a transformation function that can be used for any data type. The latter two functions are mainly used to convert strings to numbers. The three functions also perform different operations on the same arguments.

    The Number() function performs the conversion based on the following rules.

    • Boolean values that convert true to 1 and false to 0.

    • Value, return directly.

    • Null returns 0.

    • Undefined, return NaN.

    • String, apply the following rules.

      • If the string contains numeric characters, including those preceded by plus or minus signs, it is converted to a decimal value. Therefore, Number(“1”) returns 1, Number(“123”) returns 123, and Number(“011”) returns 11 (ignoring the preceding zeros).
      • If the string contains a valid floating-point value format such as “1.1”, it is converted to the corresponding floating-point value (again, the preceding zeros are ignored).
      • If the string contains a valid hexadecimal format such as “0xf”, it is converted to the decimal integer value corresponding to the hexadecimal value.
      • If it is an empty string (containing no characters), 0 is returned.
      • If the string contains characters other than the above, NaN is returned.
    • Object that calls the valueOf() method and converts the returned value according to the rules above. If the conversion results in a NaN, the toString() method is called and converted according to the rules for converting strings.

    Conversion from different data types to values can sometimes be complicated, as you can see from the conversion rules for Number(). Here are a few specific examples:

    let num1 = Number("Hello world!" ); // NaN let num2 = Number(""); // 0 let num3 = Number("000011"); // 11 let num4 = Number(true); / / 1Copy the code

    As you can see, the string “Hello world” is converted to NaN because it cannot find the corresponding value. The empty string is converted to 0. The string 000011 is converted to 11 because the preceding zero is ignored. Finally, true is converted to 1.

    Given the complexity and unconventionality of converting strings using the Number() function, parseInt() is usually preferred when an integer is needed.

    The parseInt() function focuses more on whether the string contains a numeric pattern. The first space in the string is ignored, and the first non-space character is converted. If the first character is not a numeric character, plus or minus, parseInt() immediately returns NaN.

    This means that an empty string also returns NaN (unlike Number(), which returns 0). If the first character is a numeric character, plus or minus, each character in turn is tested until the end of the string, or a non-numeric character is encountered.

    For example, “1234blue” would be converted to 1234 because “blue” would be completely ignored. Similarly, “22.5” is converted to 22 because the decimal point is not a valid integer character.

    1. The parseInt() function also recognizes different integer formats (decimal, octal, hexadecimal), assuming that the first character in the string is a numeric character. In other words, if a string begins with “0x”, it is interpreted as a hexadecimal integer. If a string begins with “0” and is followed by a numeric character, it is interpreted by some implementations as an octal integer in non-strict mode.

    The following examples of transformations help you understand the above rules:

    let num1 = parseInt("1234blue"); // 1234 let num2 = parseInt(""); // NaN let num3 = parseInt("0xA"); // 10, interpreted as a hexadecimal integer let num4 = parseInt(22.5); // 22 let num5 = parseInt("70"); Let num6 = parseInt("0xf"); // 15, interpreted as a hexadecimal integerCopy the code

    Different numeric formats can be confusing, so parseInt() also takes a second argument that specifies the base (base). If you know that the value to be parsed is hexadecimal, you can pass 16 as the second argument to parse correctly:

    let num = parseInt("0xAF", 16); / / 175Copy the code

    In fact, if hexadecimal arguments are provided, the “0x” at the beginning of the string can be omitted:

    let num1 = parseInt("AF", 16); // 175
    let num2 = parseInt("AF"); // NaN
    Copy the code

    In this example, the first transformation is correct and the second one fails. The difference is that for the first time, we pass in a base number as an argument, telling parseInt() to parse a hexadecimal string. The second transform detects that the first character is a non-numeric character and automatically stops and returns NaN.

    With the second parameter, you can greatly expand the type of results obtained after the transformation. Such as:

    let num1 = parseInt("10", 2); Let num2 = parseInt("10", 8); // let num3 = parseInt("10", 10); // let num4 = parseInt("10", 16); // 16 is resolved in hexadecimal formatCopy the code

    Because not passing the base argument is equivalent to letting parseInt() decide how to parse, it is recommended to always pass it the second argument to avoid parsing errors.

    Note that in most cases the parse should be in decimal, in which case 10 is passed as the second argument.

    The parseFloat() function works like parseInt() in that it detects each character from position 0. Again, it is resolved to the end of the string or to an invalid floating-point numeric character. This means that the first occurrence of the decimal point is valid, but the second occurrence is invalid, and the rest of the string is ignored. Therefore, “22.34.5” will be converted to 22.34.

    The parseFloat() function is also different in that it always ignores the zero at the beginning of the string. This function recognizes all floating-point formats discussed earlier, as well as decimal formats (starting zeros are always ignored). Hexadecimal values always return 0. Because parseFloat() only parses decimal values, you cannot specify a base. Finally, parseFloat() returns an integer if the string represents an integer (with no decimal point or only a zero after the decimal point). Here are a few examples:

    let num1 = parseFloat("1234blue"); Let num2 = parseFloat("0xA"); // 0 let num3 = parseFloat("22.5"); // 22.5 let num4 = parseFloat("22.34.5"); // let num5 = parseFloat("0908.5"); // 908.5 let num6 = parseFloat("3.125e7"); / / 31250000Copy the code

3.4.6 type String

The String data type represents a sequence of zero or more 16-bit Unicode characters. Strings can be marked with double quotes (“), single quotes (‘), or backquotes (‘), so the following code is legal:

let firstName = "John";
let lastName = 'Jacob';
let lastName = `Jingleheimerschmidt`
Copy the code

Unlike in some languages where different quotation marks change the way strings are interpreted, ECMAScript syntax does not differentiate quotation marks from strings. Note, however, that if you start a string with a quotation mark, you must still end the string with that quotation mark. For example, the following syntax is incorrect:

let firstName = 'Nicholas"; // Syntax error: The opening and closing quotation marks must be the sameCopy the code

I’ll do a separate article on strings

3.4.7 Symbol type

String and symbol will be published separately tomorrow. There are too many contents

3.4.8 Object type

An object in ECMAScript is simply a collection of data and functionality. Objects are created by the new operator followed by the name of the object type. Developers can create their own objects by creating instances of type Object and then adding properties and methods to the objects:

let o = new Object();
Copy the code

This syntax is similar to Java, but ECMAScript only requires that parentheses be used when supplying arguments to constructors. If there are no arguments, as in the example above, then you can omit the parentheses entirely (not recommended) :

let o = new Object; // Legal, but not recommendedCopy the code

An instance of Object by itself is not very useful, but it is important to understand the concepts associated with it. Like java.lang.Object in Java, Object in ECMAScript is the base class from which other objects are derived. All properties and methods of type Object also exist on derived objects.

Each Object instance has the following properties and methods.

  • Constructor: The function used to create the current object. In the previous example, the value of this property was the Object() function.
  • HasOwnProperty (propertyName) : Used to determine whether a given property exists on the current object instance (not the prototype). The property name to be checked must be a string (such as O.hasownProperty (“name”)) or a symbol.
  • IsPrototypeOf (object) : Used to determine whether the current object is the prototype of another object. (Chapter 8 covers prototypes in more detail.)
  • PropertyIsEnumerable (propertyName) : Used to determine if a given property can be enumerable in a for-in statement (discussed later in this chapter). As with hasOwnProperty(), the property name must be a string.
  • ToLocaleString () : Returns a string representation of an object that reflects its localized execution environment.
  • ToString () : Returns a string representation of an object.
  • ValueOf () : Returns the string, numeric, or Boolean representation of an object. Usually the same as the return value of toString().

Because Object is the base class of all objects in ECMAScript, any Object has these properties and methods. Chapter 8 covers inheritance between objects.

Note that strictly speaking, the behavior of objects in ECMA-262 does not necessarily apply to other objects in JavaScript. For example, BOM and DOM objects in the browser environment are host objects defined and provided by the host environment. Host objects are not bound by ECMA-262, so they may or may not inherit Object.