An array of

Unlike other strongly typed languages, arrays can hold any type of value in JavaScript

The delete operator removes cells from an array, but the length property of the array does not change after the cells are deleted

// Sparse array
var a = []
a[0] = 1
a[2] = [3]
a[1= = ="undefined"
a.length === 3
Copy the code

Arrays are indexed by numbers, but interestingly they are also objects, so they can also contain string keys and attributes (but these do not count in the length of the array)

An array of class

Sometimes it is necessary to convert a class array (a set of values indexed numerically) into a real array, usually through array utility functions (such as indexOf(…)). , concat (…). , forEach (…). And so on

For example, some DOM queries return lists of DOM elements that are not really arrays, but are quite similar. Another example is using arguments objects (arrays of classes) to access function arguments as lists (deprecated at ES6).

Utility function Slice (…) Often used for this type of conversion:

function foo () {
    var arr = Array.prototype.slice.call(arguments)
    arr.push("bam")
    console.log(arr)
}
foo("bar"."baz"); // ["bar", "baz", "bam"]

// Use the built-in ES6 utility function 'array. from(...). 'can do the same thing
var arr = Array.from(arguments)
Copy the code

string

Strings and arrays are indeed very similar in that they are both arrays of classes and both have the length attribute and indexOf(…). And concat (…). methods

Strings and character arrays in JavaScript are not the same thing,

var a = "foo"
var b = ["f"."o"."o"]

a.length === 3
b.length === 3

a.indexOf("o") = = =1
b.indexOf("o") = = =1

var c = a.concat("bar") // "foobar"
var d = b.concat(["b"."a"."r"]) // ["f", "o", "o", "b", "a", "r"]

a === c // false
b === d // false

// But that doesn't mean they're all character arrays
a[1] = 'O'
b[1] = 'O'

a // "foo"
b // ["f", "O", "o"]
Copy the code

In JavaScript strings are immutable while arrays are mutable, and a[1] is not always legal syntax in JavaScript. The correct method should be a.charat (1).

String immutable means that the member functions of a string do not change their original values, but instead create and return a new string, whereas the member functions of an array operate on their original values

Many array functions are handy for handling strings, and although strings don’t have these functions, strings can be handled by “borrowing” non-changing methods of arrays

var a = "foo"
a.join // undefined
a.map // undefined

var c = Array.prototype.join.call(a, The '-')
var d = Array.propotype.map.call(a, v= > {
    return v.toUpperCase() + "."
})
Copy the code

Arrays have a variable member function reverse() that strings don’t have

Unfortunately, we can’t borrow the mutable member functions of arrays because strings are immutable

So, we need to take a rough approach:

var a = "foo"
var c = a.split("").reverse().join("")
c // "oof"
Copy the code

This approach, while crude, works perfectly well for simple strings

digital

JavaScript has only one numeric type: number, including “integer” and decimal numbers with decimals, where “integer” is quoted because, unlike other languages, JavaScript doesn’t really have integers

Like most modern programming languages, the number types in JavaScript are implemented based on the IEEE 754 standard, often referred to as “floating point numbers.” JavaScript uses the “double precision” format (64-bit binary)

Syntax of numbers

// Numeric constants are generally expressed in decimal notation
var a = 42
var b = 42.3

// The 0 before the number can be omitted
var c = 0.42
var d = 42.

// The last 0 after the decimal point can also be omitted
var f = 42.0
var g = 42.

// Extremely large and extremely small numbers are shown in exponential format by default, the same output as the 'toExponential()' function
var a = 5E10
a / / 50000000000
a.toExponential() // 5e+10

var b = a * a
b / / 2.5 e+21

var c = 1/a
c // 2e-11
Copy the code

Because numeric values can be encapsulated using Number objects, numeric values can call methods in number.Prototype

var a = 42.59

a.toFixed(0) / / 43
a.toFixed(1) / / 42.6
a.toFixed(2) / / 42.59
a.toFixed(3) / / 42.590

a.toPrecision(1) // 4e+1
a.toPrecision(2) / / 43
a.toPrecision(3) / / 42.6
a.toPrecision(4) / / 42.59
a.toPrecision(5) / / 42.590
Copy the code

These methods also work with numerical constants, however

// Invalid syntax
42.toFixed(3)

// Valid syntax
(42).toFixed(3)
0.42.toFixed(3)
42..toFixed(3)
42 .toFixed(3)
Copy the code

Because a numeric constant is a valid numeric character, it is recognized as part of the numeric constant before the object property access operator

Smaller number

The biggest problem with binary floating-point numbers:

0.1 + 0.2= = =0.3 // false
Copy the code

The most common way to do this is to set a range of error, often referred to as “machine accuracy,” which is usually 2^-52 for JavaScript numbers

Starting with ES6, this value is defined in number. EPSILON, which we can either use directly or polyfill for versions prior to ES6:

if (!Number.EPSILON) {
    Number.EPSILON = Math.pow(2, -52)}function numbersCloseEnoughToEqual(n1, n2) {
    return Math.abs(n1 - n2) < Number.EPSILON
}

var a = 0.1 + 0.2
var b = 0.3

numbersCloseEnoughToEqual(a, b) // true
Copy the code

The maximum Number of floats that can be rendered is about 1.798e+308, which is defined in number. MAX_VALUE. The minimum Number is defined in number. MIN_VALUE, which is about 5e-324, which is not negative but is infinitely close to 0

The safe range of integers

The way numbers are rendered determines that the safe range for “integer” is much smaller than number.max_value

The maximum integer that can be “safely” rendered is 2^ 53-1, defined as number. MAX_SAFE_INTEGER in ES6, and the minimum integer is -(2^ 53-1), defined as number.min_safe_INTEGER in ES6

Integer detection

//ES6
Number.isInteger(42) // true
Number.isInteger(42.000) // true
Number.isInteger(42.3) // false

// before ES6 polyfill
if (!Number.isInteger) {
    Number.isInteger = function (num) {
        return typeof num === "number" && num % 1= = =0}}// ES6 
Number.isSafeInteger(Number.MAX_SAFE_INTEGER) // true
Number.isSafeInteger(Math.pow(2.53)) // false
Number.isSafeInteger(Math.pow(2.53) - 1) // false

// before ES6 polyfill
if (!Number.isSafeInteger) {
    Number.isSafeInteger = function(num) {
        return Number.isInteger(num) &&
            Math.abs(num) <= Number.MAX_SAFE_INTEGER
    }
}
Copy the code

32 – bit signed integer

Although integers can be up to 53 digits, some numeric operations (such as digit operations) only work with 32 digits, so the safe range of numbers in these operations is much smaller, ranging from math.pow (-2,31) (-2147483648, Approx. -2.1 billion) to Math.Pow (2,31) -1 (2,147,483647, approx. 2.1 billion).

A | 0 can converts the value in variable a 32-bit signed integer, because the operator | is only applicable to 32-bit integer (it only CARES about the 32-bit value, within other digital will be ignored), therefore with 0 operation can intercept a 32-bit digital

The special numerical

Not the value of the value

Undefined has only one value, that is, undefined. The NULL type also has only one value, null. Their names are both types and values

Undefined and null are often used to refer to “empty” or “non-value” values. There are some subtle differences between the two. Such as:

  • Null refers to an empty value
  • Undefined means missing value.

Null is a special keyword, not an identifier, and cannot be used and assigned as a variable. Undefined, however, is an identifier that can be used and assigned as a variable (non-strict mode)

Void operator.

var a = 42
void a  // undefined
a / / 42
Copy the code

Special numbers

  • Not a number of numbersNaN
var a = 2 / "foo"
a === NaN // false
NaN! = =NaN // true
Copy the code

NaN is a special value that is not equal to itself and is the only value that is not reflexive

var a = 2 / "foo"
var b = "foo"

a // NaN
b // "foo"

window.isNaN(a) // true
window.isNaN(b) // true ———— dizzy!
Copy the code

Obviously “foo” is not a number, but it’s not NaN either. This bug has been around for as long as JavaScript has been around, more than 19 years now

But starting with ES6 we can use the utility function number.isnan (..)

// before ES6 polyfill
if (!Number.isNaN) {
    Number.isNaN = function(n) {
        return (
            typeof n === "number" && window.isNaN(n)
        )
    }
}
var a = 2 / "foo";
var b = "foo";
Number.isNaN( a ); // true
Number.isNaN( b ); / / false - good!

// There is an easier way

if (Number.isNaN) {
    Number.isNaN = function(n) {
        returnn ! == n } }Copy the code
  • An infinite number ofInfinity
var a = 1 / 0; // Infinity 
var b = -1 / 0; // -Infinity

var a = Number.MAX_VALUE; / / 1.7976931348623157 e+308
a + a; // Infinity
a + Math.pow( 2.970 ); // Infinity
a + Math.pow( 2.969 ); / / 1.7976931348623157 e+308
Copy the code

Number.POSITIVE_INfiNITY

Number.NEGATIVE_INfiNITY

  • Zero value
var a = 0 / -3 / / - 0
var b * -3 / / - 0
// Adding and subtracting does not yield negative zero

// Stringing negative zero returns' 0 '
a.toString() / / "0"
a + "" / / "0"
String(a) / / "0"
JSON.stringify(a) / / "0"

// The reverse is true
+ "0" / / - 0
Number("0") / / - 0
JSON.parse("0") / / - 0

/ / to compare
-0= = =0 // true

/ / to distinguish
function isNegZero (n) {
    n = Number(n)
    return (n === 0) && (1/n === -Infinity)}Copy the code

A special equation

// ES6
var a = 2 / "foo";
var b = -3 * 0;
Object.is( a, NaN ); // true
Object.is( b, -0 ); // true
Object.is( b, 0 ); // false

// before ES6 polyfill
if (!Object.is) {
    Object.is = function(v1, v2) {
        // Check if it is -0
        if (v1 === 0 && v2 === 0) {
            return 1 / v1 === 1 / v2;
        }
        // Check if it is NaN
        if(v1 ! == v1) {returnv2 ! == v2; }// Other circumstances
        return v1 === v2;
    };
}
Copy the code

Value and reference

var a = 2;
var b = a; // b is a copy of a
b++;
a; / / 2
b; / / 3
var c = [1.2.3];
var d = c; // d is a reference to [1,2,3]
d.push( 4 );
c; / / [1, 2, 3, 4]
d; / / [1, 2, 3, 4]
Copy the code

Simple values are always assigned/passed by value copy

Composite values ———— objects, functions, are always assigned/passed by reference copy

Because references refer to values, not variables, one reference cannot change the direction of another

var a = [1.2.3];
var b = a;
a; / / [1, 2, 3]
b; / / [1, 2, 3]
/ / then
b = [4.5.6];
a; / / [1, 2, 3]
b; / / (4 and 6)
Copy the code

Function arguments often cause confusion like this:

function foo(x) {
    x.push( 4 );
    x; / / [1, 2, 3, 4]
    / / then
    x = [4.5.6];
    x.push( 7 );
    x; / / (4, 7)
}
var a = [1.2.3];
foo( a );
a; // is [1,2,3,4], not [4,5,6,7]

// to change the value of a to [4,5,6,7], you must change the array to which x points instead of assigning a new array to x
function foo(x) {
    x.push( 4 );
    x; / / [1, 2, 3, 4]
    / / then
    x.length = 0; // Empty the array
    x.push( 4.5.6.7 );
    x; / / (4, 7)
}
var a = [1.2.3];
foo( a );
a; // is [4,5,6,7], not [1,2,3,4]
Copy the code

We can’t decide for ourselves whether to use value copy or reference copy, it all depends on the type of value

Unlike references/Pointers in other languages, references in JavaScript cannot point to other variables/references, only to values