Recent mind has come up to the idea of “read more books, but I personally don’t like reading books, on the other hand also because I can read out time is trivial, so just use the app to see ebook (if there is a complete reading time, or suggest the paper books, layout looks more comfortable). Given that most of the problems I encounter at work are still javascript related, I chose to start with the Definitive guide to javascript, Edition 6.

The Definitive guide to Javascript 6th edition

What are the data types?

Javascript data types fall into two categories: primitive types and object types.

The original type

Primitive types are also called primitive types, including Number, String, Boolean, Undefined, and Null. In particular, undefined is the only value of undefined; Similarly, NULL is the only value of type NULL.

In addition, ES6 introduces a special primitive type Symbol, which is used to represent a unique value. For specific usage methods, you can refer to Teacher Ruan Yifeng’s Introduction to ECMAScript6, or directly browse MDN. I usually read MDN, which feels authoritative and has a perfect API.

Symbol is a primitive type and not an object type. Because we know that most programmers don’t have an object, the quickest way to find a girlfriend is to get a new one.

const options = {
    'character': 'good'.    'Appearance level': 'high'.    'to me': 'good'
}
const gf = new GirlFriend(options) // A new girlfriend Copy the code
A skin

Symbol() ¶ Symbol() ¶ Symbol() ¶ Symbol() has no constructor.

But the value of the symbol type is obtained by calling the Symbol function.

const symbol1 = Symbol('Tusi')
Copy the code

Symbol value is unique, so the following equation is not true.

Symbol(1) = = =Symbol(1) // false
Copy the code

Object type

Object types are also referred to as reference types. To put it simply, an object is a collection of key:value pairs. Common Object types are Object, Array, Function, Date, RegExp, etc.

In addition to these, Javascript has quite a few global objects, as described in the Javascript standard built-in objects. But just because a global object is a type doesn’t mean it’s an object type, just like JSON is a global object, but it’s not a type, so let’s be clear.

Object(); Array(); Object(); Array();

var obj = new Object(a)// However, we would not normally write an ordinary object like this
var arr1 = new Array(1) // Create an empty array with length 1
var arr2 = new Array(1.2) // Create an array [1, 2]
Copy the code

Stack memory and heap memory

Stack memory has the advantage of being faster to access than heap memory, which can actually optimize code performance.

Stack memory

Primitive types are accessed by value, and their values are stored in stack memory of known or limited size.

A reassignment of a primitive type variable is essentially a stack push, writing a new value and pointing it to a block of top elements.

var a = 1; // push the stack, 1 becomes the top element, and its value is assigned to variable A
a = 2; // Push 2 to the top of the stack and assign it to variable A (memory address changed)
Copy the code

Heap memory

Whereas object types are accessed by reference, objects are accessed through Pointers.

A pointer is an address value, similar to a primitive type, stored in stack memory and used as an intermediary for variable access to objects.

The object itself is stored in heap memory, and its memory footprint is variable and unknown.

Examples are as follows:

var b = { name: 'Tusi' }
Copy the code

Running this line of code creates a memory space in the heap for the object {name: ‘Tusi’} and declares a pointer to the memory address of the object. The pointer is assigned to the reference variable B, which means that B refers to the object.

Objects can add or delete attributes, so the amount of memory used by object types is generally unknown.

b.age = 18; // Add the age attribute to the object
Copy the code

So what does access by reference mean?

Object operations on a reference variable essentially change the object itself at the heap memory address to which the reference variable points.

This means that if there are two or more reference variables referring to the same object, an operation on one of the reference variables will affect the other reference variables referring to that object.

var b = { name: 'Tusi' }; // Create an object with the variable b pointing to it
var c = b; // declare variable c, pointing to the same as b
b.age = 18; // Modify the object with variable b
// Produces side effects, c is affected
console.log(c); // {name: "Tusi", age: 18}
Copy the code

Given the side effects of object manipulation, we often use deep copy in business code to circumvent this problem.

Data type judgment

Determining data types is one of the most important infrastructures, so how do you determine data types? Please read on.

typeof

Javascript itself provides typeof operators to help us determine data types.

The typeof operator returns a string representing the typeof the unevaluated operand.

The result of typeof operation is as follows, which is referenced from MDN Typeof

The data type Operation results
Undefined “undefined”
Null “object”
Boolean “boolean”
Number “number”
String “string”
Symbol “symbol”
Function “function”
Other objects “object”
Host object (provided by the JS environment, e.g. Nodejs has global, browser has Window) It depends on the implementation

As you can see, Typeof helps us identify most data types, but note that:

  1. typeof nullAs a result"object"
  2. There are many kinds of objects,typeofYou can’t judge arrays, ordinary objects, or other special objects

So how do you know exactly what the data type of a variable is?

Combining with the instanceof

The instanceof operator is used to check whether the constructor’s prototype property appears on the prototype chain of an instance object.

Using instanceof, we can determine if an object is an instanceof a constructor. So with Typeof, we can encapsulate a basic function that determines the data type.

Typeof returns “object”, if not, it is a common data type, then return the result of typeof operation directly. If so, you need to pick the null trap first, and then determine the other object types in turn.

function getType(val) {
    const type = typeof val;
    if (type === 'object') {
        if (val === null) {
            // Null is not an object, so it cannot be determined by instanceof
 return 'null'  } else if (val instanceof Array) {  return 'array'  } else if (val instanceof Date) {  return 'date'  } else if (// Instanceof judgment for other objects) {  return 'xxx'  } else if (val instanceof Object) {  // All objects are instances of Object, so put last  return 'object'  }  } else {  return type  } } / / under test getType(Symbol(1)) // "symbol" getType(null) // "null" getType(new Date()) // "date" getType([1.2.3]) // "array" getType({}) // "object" Copy the code

However, listing all the commonly used object types is a bit cumbersome, so it’s not an elegant approach.

ToString, the ultimate artifact

Is there a final solution? Of course there is. But, not toString in the title, but the Object. The prototype. ToString. Using it, not only the above data types can be determined, but also some new object types introduced in ES6, such as Map, Set, etc.

/ / use the Object. The prototype. ToString capture set and regular expressions
function getType(val) {
    return Object.prototype.toString.call(val).replace(/\[object\s(\w+)\]/.'$1').toLowerCase();
}

getType(new Map()) // "map" getType(new Set()) // "set" getType(new Promise((resolve, reject) = > {})) // "promise" Copy the code

Why can’t the ordinary call the toString judgment data types, and the Object. The prototype. ToString can?

Object is a base class, and all derived classes, such as Date and Array, overwrite the toString method to express their own business when inheriting Object, thus losing the ability to judge the type.

Packing and unpacking

First, let’s explain what boxing and unboxing are. The operation of converting a primitive type to the corresponding object type is called boxing, and vice versa.

packing

We know that only objects can have properties and methods, but we can call some of their properties and methods directly when we use data of primitive types.

var a = 1;
a.toFixed(2); / / "1.00"

var b = 'I love study';
b.length; / / 12
b.substring(2.6); // "love" Copy the code

When reading properties or methods of primitive data, javascript creates temporary objects (also known as “wrapper objects”) through which to read properties or methods. The above code is equivalent to:

var a = 1;
var aObj = new Number(a);
aObj.toFixed(2); / / "1.00"

var b = 'I love study';
var bObj1 = new String(b); bObj1.length; / / 12 var bObj2 = new String(b); bObj2.substring(2.6); // "love" Copy the code

Temporary objects are read-only, meaning that they are destroyed after a read, so you cannot define new properties for them or modify their existing properties.

var c = '123'; c.name = 'jack'; // Adding new attributes to temporary objects is invalid c.name; // undefined c.length; // 3 c.length = 2; // Modify temporary object attribute value, is invalid c.length; / / 3Copy the code

We can also do boxing explicitly, that is, explicitly create the wrapped object using the String(), Number(), Boolean() constructors.

var b = 'I love study';
var bObj = new String(b);
Copy the code

Split open a case

Unboxing objects is done using valueOf and toString, as we’ll see below.

Type conversion

Javascript will automatically perform type conversions in certain scenarios, and we will also perform data type conversions based on business needs. Type conversion rules are as follows:

Type conversion rules

The conversion of an object to its original value

toString

ToString () is the default object-to-string conversion method.

var a = {};
a.toString(); // "[object Object]"
Copy the code

But many classes have custom toString() methods, for example:

  • Array: Concatenates Array elements with commas into strings as return values.
var a = [1.2.3];
a.toString(); / / 1, 2, 3
Copy the code
  • Function: Returns a string containing the source code of the Function.
  • Date: Returns a Date and time string.
var a = new Date(a);a.toString(); // "Sun May 10 2020 11:19:29 GMT+0800"
Copy the code
  • RegExp: Returns a string representing the direct quantity of the regular expression.
var a = /\d+/;
a.toString(); // "/\d+/"
Copy the code

valueOf

ValueOf () returns the Object itself by default, including Object, Array, Function, and RegExp.

The Date class overrides the valueOf() method to return the number of milliseconds since January 1, 1970.

var a = new Date(a);a.toString(); / / 1589095600419
Copy the code

Object –> Boolean

As you can see from the table above, objects (including arrays and functions) are converted to Booleans with true.

Object –> string

The basic rules for converting objects to strings are as follows:

  • If the object hastoString()Method is called. If it returns a string, it is the result of the conversion; If it returns another raw value, the original value is converted to a string as a result of the conversion.
  • If the object doesn’t havetoString()Method, ortoString()Do not return the original value (do not return the original value of this case is not seen, usually custom classtoString()Method), thenjavascriptWill be calledvalueOf()Methods. If there isvalueOf()Methods andvalueOf()Method returns a raw value,javascriptConverts this value to a string (if the original value is not itself a string) as a result of the conversion.
  • Otherwise,javascriptfromtoString()orvalueOf()If you get a raw value, an exception is thrown.

Object –> number

This is similar to the object-to-string rule, except that valueOf() is called first.

  • If the object hasvalueOf()Method, andvalueOf()Returns a raw value, thenjavascriptConverts this original value to a number (if the original value is not a number itself) as a result of the conversion.
  • Otherwise, if the object hastoString()Method and returns a raw value,javascriptConvert this raw value to a number as a result of the conversion.
  • Otherwise,javascriptA type error exception will be thrown.

According to conversion

Cast type using String(), Number(), Boolean() functions.

var a = 1;
var b = String(a); / / "1"
var c = Boolean(a); // true
Copy the code

Implicit conversion

In different usage scenarios, javascript implicitly converts the type based on the actual situation. Let me give you a couple of examples.

The addition operator +

Some of the more familiar operators are the arithmetic operators +, -, *, /, of which the special one is +. Because the addition operator + can be used for numeric addition as well as string concatenation, the two operands of the addition operator may be of different types.

When the two operands are of different types, the addition operator + has the following rules.

  • If one of the operators is an object, the object-to-primitive conversion rules are followed. For non-date objects, the object-to-primitive conversion is basically an object-to-number conversion, so it is called firstvalueOf()Whereas most objectsvalueOf()The value returned is the object itself, not a raw value, so it is also calledtoString()To get the original value. For date objects, object-to-string conversions are used, so call firsttoString().
1 + {}; // "1[object Object]"
1 + new Date(a);// "1Sun May 10 2020 22:53:24 GMT+0800"
Copy the code
  • After converting the object to the original value, if the addition operator+If one of the operands of is a string, the other operand is also converted to a string, and a string concatenation is performed.
var a = {} + false; // "[object Object]false"

var b = 1 + []; / / "1"
Copy the code
  • Otherwise, both operands are converted to numbers (or nans) and then added.
var a = 1 + true; / / 2

var b = 1 + undefined; // NaN

var c = 1 + null; / / 1
Copy the code

[] = =! []

Another classic example is [] ==! [], the result is true. A look, is not feel a little meng, a value of the inverse is also equal to the value! In fact, a careful analysis of the process, can be found in the mystery.

  1. First of all, we need to know the precedence of the operator, unary operator!Has precedence over relational operators= =.
Js operator priority
  1. So, the right-hand side! []Execute first, and logic is not an operator!It first converts its operand to a Boolean and then inverts it.[]Convert to a Boolean value oftrue, so! []As a result of thefalse. Now the comparison becomes 1, 2, 3[] == false.
  2. According to the rules of comparison, if= =One of the values of theta is thetafalse, converts it to a number0, and compare it with another operand. Now the comparison becomes 1, 2, 3[] = = 0.
  3. Then, referring to the comparison rules, if one value is an object and the other is a number or string, the object is converted to its original value and then compared. On the left side of the[]The original value is an empty string""So now the comparison becomes"" = = 0.
  4. Finally, if one value is a number and the other is a string, the string is converted to a number and then compared. Empty strings are converted to numbers0.0with0Nature is equal.

{} ==! {} ==! {} is false, so this is easier.

Do you still think data types are simple? Those interested in further research can consult the authoritative explanation of ES5.

The last

Data type is a very important part of javascript. It is beneficial to understand the basic knowledge of data type for the subsequent knowledge of learning javascript.

In addition, taking notes can actually be very helpful in thinking about problems, even if it’s just summarizing the basics.

The above content is a personal note and summary, there are mistakes or omissions, welcome to leave a message.

Welcome to communicate