A variable can hold two types of values: Primitive values and reference values.

ES6 introduces a new primitive data type, Symbol, that represents unique values. It is the seventh data type in JavaScript, with Undefined, Null, Boolean, String, Number, and Object being the first six.

Basic types of

There are six basic data types in JavaScript: Undefined, Null, Boolean, Number, String, Symbol (new in ES 6)!

Convention: primitive data type and primitive data type.

Values of basic data types are accessed by value.

  • Values of primitive types are immutable

    var str = "123hello321";
    str.toUpperCase();     // 123HELLO321
    console.log(str);      // 123hello321
    Copy the code
  • A comparison of primitive types is a comparison of their values

    var a = 1;
    var b = true;
    console.log(a == b);    // true
    console.log(a === b);   // false
    Copy the code

    The data types of A and B above are different, but it is also possible to compare values because an implicit conversion of the data types is automatically performed before the comparison.

    • = =: Compares values only
    • = = =: Not only value comparison, but also data type comparison
  • Variables of basic types are stored in the Stack

    var a,b;
    a = "zyj";
    b = a;
    console.log(a);   // zyj
    console.log(b);   // zyj
    a = "Ha ha";       // Change the value of a does not affect the value of b
    console.log(a);   / / ha ha
    console.log(b);   // zyj
    Copy the code

The stack memory contains the identifier of the variable and its value

Reference types

Apart from the six basic data types mentioned above, all that remains are reference types, collectively known as Object types. Subdivided, there are: Object, Array, Date, RegExp, Function, and so on.

Values of reference types are accessed by reference.

  • The value of a reference type is mutable

    var obj = {name:"zyj"};   // Create an object
    obj.name = "percy";       // Change the name attribute
    obj.age = 21;             // Add the age attribute
    obj.giveMeAll = function(){
      return this.name + ":" + this.age;
    };                        // Add the giveMeAll method
    obj.giveMeAll();
    Copy the code
  • A comparison of reference types is a comparison of references

    var obj1 = {};    // Create an empty object, obj1
    var obj2 = {};    // Create an empty object obj2
    console.log(obj1 == obj2);    // false
    console.log(obj1 === obj2);   // false
    Copy the code

    Since obj1 and obj2 refer to two different objects stored in the heap, the values of obj1 and obj2 are different!

  • The value of the reference type is an Object stored in the Heap.

    Unlike other programming languages, JavaScript cannot directly manipulate the memory space of an object (heap memory).

    var a = {name:"percy"};
    var b;
    b = a;
    a.name = "zyj";
    console.log(b.name);    // zyj
    b.age = 22;
    console.log(a.age);     / / 22
    var c = {
      name: "zyj".age: 22
    };
    Copy the code

    The diagram is as follows:

    • Stack memory holds the variable identifier and a pointer to the object in heap memory

    • The heap memory holds the contents of the object

Detection of type

  • Typeof: Usually detects the base type.

    1. For basic types, all but null returns the correct result. 2. For reference types, return object except function. 3. For null, return object.

4. Return function type for function.

var a;
typeof a;    // undefined

a = null;
typeof a;    // object

a = true;
typeof a;    // boolean

a = Awesome!;
typeof a;    // number 

a = "hello";
typeof a;    // string

a = Symbol(a);typeof a;    // symbol

a = function(){}
typeof a;    // function

a = [];
typeof a;    // object
a = {};
typeof a;    // object
a = /aaa/g;
typeof a;    // object   
Copy the code
  • Instanceof: usually checks the reference type to determine whether A is an instanceof B

    ({}) instanceof Object              // true
    ([]) instanceof Array               // true
    (/aa/g) instanceof RegExp           // true
    (function(){}) instanceof Function  // true
    Copy the code
  • Object. The prototype. ToString: usually detection basic types and reference types. You can identify exactly which built-in type an object value belongs to, more accurately than typeof & Instanceof.

    [[Class]] is an internal attribute of any built-in object. The value is a type string that can be used to determine the type of the value.

    In JavaScript code, the only way can access this property is through the Object. The prototype. ToString, usually as follows:

    Object.prototype.toString.call(value)
    Copy the code
    Object.prototype.toString.call(123) // '[object Number]'
    Object.prototype.toString.call('123') // '[object String]'
    Object.prototype.toString.call(null) // '[object Null]'
    Object.prototype.toString.call(undefined) // '[object Undefined]'
    Object.prototype.toString.call(Math) // '[object Math]'
    Object.prototype.toString.call({}) // '[object Object]'
    Object.prototype.toString.call([]) // '[object Array]'
    ({}).toString() // [object Object]
    Copy the code

Type conversion

Because JS is a weakly typed language, type conversions occur very frequently, and most familiar operations begin with type conversions.

Fortunately, most of the conversion rules are actually quite simple, as shown in the following table:

In this case, the more complicated parts are the conversions between Number and String, and between objects and primitive types. Let’s take a look at the rules for each transformation.

1. StringToNumber

String to number conversions, there is a syntax structure, type conversions support decimal, binary, octal, and hexadecimal, for example:

  • 30; // Decimal => 30
  • 0 b111; // Binary => 7
  • 0 o13; // octal => 11
  • 0 XFF. // Hexadecimal => 255
  • 1e3; // Scientific counting => 1000
  • 1 e – 2; // Scientific counting => -0.01

Other types => NaN

2. NumberToString

On a smaller scale, the numeral-to-string conversion is a decimal representation that perfectly conforms to your intuition.

console.log(1e3 + 'ok'); // 1000ok
Copy the code

3. Boxing conversion (basic type => Object)

Each basic type Number, String, Boolean, Symbol have corresponding classes in the object, the so-called boxing conversion, is to convert the basic type into the corresponding object, it is a rather important type conversion.

Attention! The boxing mechanism frequently produces temporary objects, and in some performance-critical scenarios, we should avoid boxing primitives.

For example, the number below does not change and only the numberObj temporary object is generated.

Scenario 1: We can use the call method of a function to force boxing.

var number = 123;
var numberObj = (function(){ return this; }).call(number);
numberObj instanceof Number; // true
number instanceof Number; // false 
Copy the code

Scenario 2: Using the built-in Object function, we can explicitly invoke the boxing capability in JavaScript code.

var number = 123;
var numberObj = Object(number);
numberObj instanceof Number; // true
number instanceof Number; // false 
Copy the code

4. Unpacking conversion (Object => Basic type)

In the JavaScript standard, ToPrimitive is defined as a function that converts object types ToPrimitive types (i.e., unboxed conversions).

The unboxed conversion attempts to call valueOf and toString to get the unboxed base type. If neither valueOf nor toString exists, or if no primitive type is returned, a TypeError is generated.

var o = {
    valueOf : () = > {console.log("valueOf"); return {}},
    toString : () = > {console.log("toString"); return {}}
}

o * 2 / o + ' '
// valueOf
// toString
// TypeError
Copy the code

As you can see, a typical operation would execute valueOf first, then toString, and finally raise a TypeError, indicating that the unboxing conversion failed.

The unboxing conversion toString calls toString first. Let’s change this operation from o*2 to String(o), and you’ll see that the order of calls has changed.

String(o) 
// toString 
// valueOf 
// TypeError
Copy the code

After ES6, objects are also allowed to override the original behavior by explicitly specifying the @@Toprimitive Symbol.

var o = {
  valueOf : () = > {console.log("valueOf"); return {}},
  toString : () = > {console.log("toString"); return {}}
}

o[Symbol.toPrimitive] = () = > {console.log("toPrimitive"); return "hello"}


console.log(o + "")
// toPrimitive
// hello
Copy the code

Question time

  1. Why do some programming specifications require void 0 instead of undefined?

    Because JavaScript code uses undefined as a variable rather than a keyword, which is one of the most recognized design mistakes of the JavaScript language, we recommend using void 0 to get undefined to avoid inadvertent tampering.

  2. Isn’t 0.1 + 0.2 equal to 0.3? Why isn’t that the case in JavaScript?

    By floating-point definition, non-integer Number types cannot be compared using == (nor can ===) :

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

    In fact, what is wrong here is not the conclusion, but the method of comparison, and the correct method of comparison is to use the minimum precision provided by JavaScript:

    console.log( Math.abs(0.1 + 0.2 - 0.3) < =Number.EPSILON); // true
    Copy the code
  3. Why do methods added to objects work on primitive types?

    The. Operator provides the boxing operation, which constructs a temporary object from the underlying type, allowing us to call the corresponding object’s methods on the underlying type.

    Number.prototype.hello = () = > console.log('hello');
    (123).hello(); // hello
    Copy the code
  4. Is a variable an array?

    var arr = [1.2.3]
    Array.isArray(arr)
    arr instanceof Array
    arr.constructor === Array
    Object.prototype.toString.call(arr) === '[object Array]'
    Copy the code

reference

  • Geek time – Relearn the front end