JavaScript variables and data types (2)


JavaScriptVariables and data types (2)

In this chapter, we will explain:

  • Special reference types
  • Type conversion
  • Get data type

1、 Special reference types

stayECMAScriptIn, a reference type is a data structure used to organize data and functions together.

Generally speaking, an object is an instance of a specific reference type.

stayECMAScriptIn the definition of type, onlyObjectType. In fact, many of the variables that we usually use to refer to type are not created byObjectConstructed, but the end of their prototype chain isObject, which are all reference types.

  • Arrayarray
  • Datedate
  • RegExpregular expression
  • Functionfunction
  • Basic type package type

1.1 packaging type

ECMAScriptFor ease of operationBasic data type, which provide special reference types. They are wrapper types of basic types

  • String
  • Boolean
  • Number

Take the string as an example

let str1 = "HelloWorld";
let str2 = new String("HelloWorld");

Pay attention to the difference between package type and basic type

true == new Boolean(true);          // true
true === new Boolean(true);         // false
123 == new Number(123);             // true
123 === new Number(123);            // false
"Hello" == new String("Hello");     // true
"Hello" === new String("Hello");    // false
console.log(typeof new String("Hello"));    // object
console.log(typeof "Hello");                // string

The main difference between a reference type and a wrapper type is the lifetime of an object. The instance of a reference type created by using the new operator is always stored in memory before the execution flow leaves the current scope, while the self basic type only exists at the moment of execution of a line of code, and then is destroyed immediately, This means that we cannot add properties and methods to the base type at run time( This passage is copied from the original

var name = 'ConardLi'
name.color = 'red';
console.log(name.color); // undefined

1.2 packing and unpacking

  • Packing: convert the basic type to the corresponding packing type
  • Unpacking: converts the package type to the basic type for

Although basic types cannot extend properties and methods, they also have some properties and methods for us to use (such aslength,slice,splitBecause every time weoperationFor a basic type, the background will automatically create an object of the corresponding wrapper type, so that when we call properties and methods, we call the wrapper type.
for instance:

var name = "ConardLi";
var name2 = name.substring(2);

The following processes occurred:

  • Create base typename
  • WhennameWhen operating, a corresponding background is createdStringType of the wrapper type of the object
  • Call on objectsubstring()method
  • Call complete, destroy object

The above process is a packing process
When we operate the basic type, we will automatically box and unpack,NumberandBooleanThe same is true

The conversion from reference type to basic type, that is, the process of unpacking, will follow theECMAScript specificationPrescribedtoPrimitiveIn general, thevalueOfandtoStringMethod, you can also rewrite it directlytoPeimitiveMethods(Symbol.toPrimitiveMethod) can also be overriddenvalueOfandtoStringmethod. Generally, the conversion to different types of values follows different principles, such as:

  • Reference type toNumberType is called firstvalueOf, and then calltoString
  • Reference type toStringType is called firsttoString, and then callvalueOf
  • ifvalueOfandtoStringIf none exists, or if no base type is returned, theTypeErrorabnormal
const obj = {
  valueOf: () => { console.log('valueOf'); return 123; },
  toString: () => { console.log('toString'); return 'hello'; },
console.log(obj - 1);   // valueOf   122
console.log(`${obj}world`); // toString  helloworld

const obj2 = {
  [Symbol.toPrimitive]: () => { console.log('toPrimitive'); return 123; },
console.log(obj2 - 1);   // valueOf   122

const obj3 = {
  valueOf: () => { console.log('valueOf'); return {}; },
  toString: () => { console.log('toString'); return {}; },
console.log(obj3 - 1);  
// valueOf  
// toString
// TypeError

In addition to the automatic unpacking and automatic packing in the program, we can also manually unpack and pack. We can directly call thevalueOfortoStringTo realize the unpacking operation:

var num =new Number("123");  
console.log(num.valueOf());             // 123;
console.log(typeof num.valueOf() );     //number
console.log(num.toString());            // '123'
console.log(typeof num.toString() );    //string

2、 Type conversion

javascriptIt’s a schoolWeakly typed languageSo type conversions often occurPackingAndUnpackingAlso a type conversion)

There are two types of conversion

  • Implicit type conversion: the automatic type conversion of the program
  • Force type conversion: the type conversion we do manually

2.1 implicit type conversion

You need to know when implicit type conversion occurs and the rules for implicit type conversion

2.1.1 implicit type conversion rules

JavaScript variables and data types (2)

2.1.2 occurrence scenarios
If statement and logic statement

The logic calculation part will be calculated to get a value, and then the logic calculation will be carried outbooleanConversion, only the following cases will be converted tofalseAnd the rest of them turned totrue

Do mathematical operations

We are notNumberType (exclStringType) when using mathematical operators, the nonNumberType toNumbertype

1 - true // 0
1 - null //  1
1 * undefined //  NaN
2 * ['5'] //  10

be careful:+No. 1 is an exception

  • When one side isStringType is recognized as string splicing, and the other side is preferentially converted to string type.
  • When one side isNumberType, and the other side is the original typeNumberType.
  • When one side isNumberType, the other side is reference type, the reference type andNumberType into string after splicing.
123 +'123 '// 123123 (rule 1)
123 + null // 123 (Rule 2)
123 + true // 124 (Rule 2)
123 + {} // 123 [object object] (Rule 3)

use==If the types of the two sides are different, the implicit conversion will occur===Judge the type to prevent implicit conversion. use==The conversion can be divided into several different situations (only considering the different types on both sides)

  • 1.NaN

NaNCompare with any other type and always returnfalse(including himself).

NaN == NaN // false
  • 2.Boolean

BooleanCompared with any other type,BooleanFirst, it is converted toNumberType.

true == 1  // true 
true == '2'  // false
true == ['1']  // true
true == ['2']  // false

Here’s a possible confusion:undefined、nullandBooleanComparison, thoughundefined、nullandfalseIt’s easy to think of them as false values, but they compare themfalse, becausefalseFirst, it’s converted to0

undefined == false // false
null == false // false
  • 3. String and number

StringandNumberFirst, compareStringConvert toNumberType.

123 == '123' // true
'' == 0 // true
  • 4. Null and undefined

null == undefinedThe result is thattrueIn addition,null、undefinedCompared with any other results, the value is 0false

null == undefined // true
null == '' // false
null == 0 // false
null == false // false
undefined == '' // false
undefined == 0 // false
undefined == false // false
  • 5. Primitive type and reference type

When the original type is compared with the reference type, the object type follows theToPrimitiveRule to original type:

  '[object Object]' == {} // true
  '1,2,3' == [1, 2, 3] // true

Let’s take a look at the following comparison:

[] == ![] // true

!Priority of is higher than==![]First, it will be converted tofalseAnd then according to the third point above,falseconvert toNumbertype0, left[]Convert to0Both sides are equal.

[null] == false // true
[undefined] == false // true

According to theToPrimitiveRule, array element isnullorundefinedThe element is treated as a short string, so[null]、[undefined]Will be converted to0

So, having said so much, it is recommended to use it===To determine whether two values are equal

Send up an interview question

A classic interview question, how to make:a == 1 && a == 2 && a == 3
According to the unpacking conversion above, and==We can easily write the answer to this question

const a = {
   valueOf: function () {return this.value.pop(); },

aAndNumberWhen comparing types, thevalueOfImplicit conversion, each conversion is deletedvalueThe last element and returns

3、 Type judgment

list4Two methods

3.1 typeof

typeofOperators can accurately determine whether a variable is of the following primitive types:

typeof 'ConardLi'  // string
typeof 123  // number
typeof true  // boolean
typeof Symbol()  // symbol
typeof undefined  // undefined

You can also use it to determine the type of function

typeof function(){}  // function

But it’s a bit unfriendly when it comes to judging reference types

typeof [] // object
typeof {} // object
typeof new Date() // object
typeof /^\d*$/; // object

All reference types except functions are determined to beobject
And:(jsIt’s a small onebug)

   tyoeof null      // object

3.2 instanceof

instanceofOperators can help us to determine what kind of object the reference type is

[] instanceof Array // true
new Date() instanceof Date // true
new RegExp() instanceof RegExp // true

Let’s review some rules of prototype chain

  • 1. Allreference typeThey all have object characteristics, that is, they can freely extend attributes
  • 2. Allreference typeThey all have one__proto__The (implicit prototype) attribute is a common object
  • 3. AllfunctionAll haveprototypeThe (explicit prototype) property is also a common object
  • 4. Allreference type__proto__Value to its constructorprototype
  • 5. When trying to get an attribute of an object, if the variable itself does not have this attribute, it will go to his own__proto__Find in the middle

[] instanceof ArrayIt’s actually judgmentArray.prototypeIs it in[]On the prototype chain.

In the same way, we can useinstanceofWhether the object to be judged and the constructor are on the same prototype chain:

let a1 = new Aaa();
let a2 = [];
console.log(a1 instanceof Aaa);     // true
console.log(a2 instanceof Aaa);     // false
console.log(a2 instanceof Array);   // true

instanceofCan’t check data type intuitively, at the same time can’t crossiframe

3.3 toString()

It is mentioned in the unpacking operationtoStringFunction, which we can call to implement the conversion from reference type.

Each reference type has atoStringMethod, by default,toString()Methods are defined by eachObjectObject inheritance. If this method is not overridden in a custom object,toString()return"[object type]"Of whichtypeIs the type of the object.

const obj = {};
obj.toString() // [object Object]

Notice, it’s mentioned aboveIf this method is not overridden in a custom objecttoStringIn fact, most of the reference types, such asArray、Date、RegExpIt’s all rewrittentoStringmethod.

We can call it directlyObjectUncovered on PrototypetoString()Method, usingcallTo changethisPoint to achieve the effect we want.
Can point toObjectTo call thetoStringMethod is not afraid of rewriting, but the code will be very lengthy

JavaScript variables and data types (2)

3.4 constructor

We can go through itconstructorTo view the correspondingConstructorsWhich also includes the type of packaging
For example:

let str = "hello";
let num = 123;
let bool = true;
console.log(str.constructor);       // String
console.log(num.constructor);       // Number
console.log(bool.constructor);      // Boolean

When we call the method of the underlying type, we will automatically call the method of its corresponding wrapper typeconstructorTo return its correspondingConstructors
Similarly, we can change the reference type:

let obj1 = {};
let obj2 = [];
console.log(obj1.constructor);      // Object
console.log(obj2.constructor);      // Array
function Aaa(){};
console.log(Aaa.constructor);       // Function

howeverconstructorCan’t judgenullAndundefinedMeeting reportTypeErrorError:

let a = null;
let b = undefined;
console.log(a.constructor);     // TypeError
console.log(b.constructor);     // TypeError

3.5 jquery

Let’s seejqueryHow to judge the type in the source code:

var class2type = {};
jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ),
function( i, name ) {
    class2type[ "[object " + name + "]" ] = name.toLowerCase();
} );

type: function( obj ) {
    if ( obj == null ) {
        return obj + "";
    return typeof obj === "object" || typeof obj === "function" ?
        class2type[ ] || "object" :
        typeof obj;

isFunction: function( obj ) {
        return jQuery.type(obj) === "function";

The original type is used directlytypeof, reference type useObject.prototype.toString.callGet type, with the help of aclass2typeObject to filter out redundant code from a string, such as[object function]Will getarrayAnd then in the following type judgment, such asisFunctionIt can be used directlyjQuery.type(obj) === "function"That’s a judgment.

3.6 advantages and disadvantages judgment

  • typeof:

Advantages: convenient and fast, accurate judgment of basic data types (exceptnull
Disadvantages: base typenullreturnobject, reference type exceptFunctionEverything else is backObject

  • instanceof:

Advantages: it can directly determine whether data and objects are on the same prototype chain
Disadvantages: unable to intuitively return data types, unable to detect basic data types, unable to crossiframe

  • toString

Advantages: adapt to various types, return more accurate data type
Disadvantages: it is easy to be rewritten, it is not easy to write and the code is lengthy to call the prototype method directly,IE6The followingundefinedandnullReturn toobject

  • constructor

Advantage: the data type returned is more precise
Disadvantages: unable to judgenullAndundefined, easy to modify, unable to crossiframe

New one, please forgive me
If there are any mistakes in this article, please send a private letter or comment.
Special thanks:Conardli’s blog

Recommended Today

Lua language novice simple tutorial

1、 Foreword Lua is a lightweight and compact scripting language, which is written in standard C language and open in the form of source code. Its design purpose is to be embedded in the application, so as to provide flexible expansion and customization functions for the application. Lua can be applied in game development, independent […]