This is the 21st day of my participation in the August More Text Challenge

I. Common test data types

There are four methods to detect data types commonly used in JS. In project development, data types are interspersed in every important link. If data type detection is skillfully used, it will often play an unexpected effect. In bug debugging, if you try to detect data types when you’re at the end of your tether, you’ll often see a silver lining. This is especially useful for nodeJS bug debugging, as Node often performs data type conversions during IO operations.

The reason why it is told in this article, data type detection, because the method of data type detection and object-oriented has inextricably linked, if you have time to look at the first three articles, I believe can have a deeper understanding of data type detection, is the so-called no pain. Idle talk less Syria, get to the point.

1, the typeof

Typeof is mostly used to detect base data types or object data type detection without specific refinement or to distinguish between base data types and reference data types. Typeof returns “number”, “string”, “Boolean”, “undefined”, “function”, “null”, “object”. Example:

console.log(typeof     5);/ / "number"
console.log(typeof"Binary");/ / "string"
console.log(typeof     true);/ / "Boolean"
console.log(typeof     undefined);/ / "undefined"
console.log(typeof  function (){});/ / "function"
console.log(typeof     null);/ / "object"
console.log(typeof     {});/ / "object"
console.log(typeof     []);/ / "object"
console.log(typeof  /^\d+$/);/ / "object"...... .Copy the code

From the above examples, it is easy to see that Typeof has limitations, which are embodied in:

  1. Returns object when null is detected
  2. Object data types cannot be specifically subdivided
  3. The function itself is not a data type, but because functions have many special features, it makes sense to return a function when typeof a function here

2, instanceof:

The instanceof operator checks whether an instance belongs to a class and returns true if it does, false otherwise. Example:

var ary=[1m,2m,23];
console.log(ary instanceof Array);//true
console.log(ary instanceof Object);//true
var num=12;var num2=new Number(12);
console.log(num instanceof Number);//false
console.log(num2  instanceof  Number);//true
Copy the code
  • butinstanceofIt has its limitations,
  1. It is not possible to detect the value of the basic data type created by a word. This is because JS is a weakly typed language. In this sense, there is a difference between instance creation and literal creation.
  2. As long as the currently checked value is in the current class’s prototype chain, the result is true;
  3. After using class inheritance, the detection result will not be accurate;

3, the constructor:

constructorIs to make up forinstanceofCannot detect data created by literals;var num= 12;console.log(num.constructor===Number);//true
var ary=[1.2.3];
console.log(ary.constructor===Array);//true;
console.log(ary.constructor===Object);//false;
Copy the code

Constructor makes up for some of the shortcomings of Instanceof, but its disadvantages cannot be ignored: when a class’s prototype is overwritten, its constructor may be modified, resulting in inaccurate detection results;

4, the Object. The prototype. ToString. Call (); methods

Each datatype comes with a toString() method, but the utility is different. A toString for a group of numbers converts to a string, while a toString for an object checks the datatype. This method returns a string, such as “[Object data class]”. The sample

var num=24;
console.log(Object.prototype.toString.call(num));/ / "[object Number]";
var ary=[1.2.3];
console.log(Object.prototype.toString.call(ary));/ / "[object Array]";
var reg=/^\w+$/g;
console.log(Object.prototype.toString.call(reg));/ / "[object RegExp]"...... .Copy the code

The last method is recommended if accurate test results are required.

Class inheritance

In the previous two articles, we introduced some of the features of objects and the common encapsulation methods of object orientation. Today, we will continue to discuss two more important aspects of object orientation: inheritance and polymorphism; Inheritance is a favorite concept of all object-oriented languages. Most of the inheritance methods described in the following are based on the prototype pattern and constructor pattern. If you want to better understand the concept of inheritance, you also hope to take a good look at the discussion of the prototype pattern in the last article. This paper focuses on several common inheritance methods, and tries to discuss the advantages and disadvantages of each inheritance method, and the Angle of the parent class method ownership after inheritance.

2.1 Prototype Inheritance

The implementation principle of prototype inheritance, the prototype of a subclass points to an instance of the parent class; So that methods and attributes that are public and private in the parent class become methods and attributes that are public in the child class; Example:

function Super(){/ / parent class
    this.delete=functinon(item){}
}
Super.prototype.edit=function(){};
function Sub(){/ / subclass}The subclass wants to call the parent classdeleteAnd edit methods, which simply point the prototype of a subclass to an instance of the parent class; Sub.prototype=new Super();// Inherit the implementation of the core code
Copy the code

Although the operation of prototype inheritance is simple, the following issues should be noted;

  1. Prototype inheritance is not a copy of the public and private attributes and methods of the parent class, but let the child class and the parent class have the link on the prototype chain, after the implementation of inheritance, the __proto__ attribute of the instance of the child class points to the instance of the parent class, and the __proto__ of the instance points to the prototype of the parent class, so the implementation of inheritance;
  2. When inheritance is realized through the prototype chain, the prototype of a subclass actually becomes an instance of another class, and the properties of the original parent class instance naturally become the properties of the subclass prototype, which we cannot change;
  3. Through prototype inheritance, the prototype of the subclass is replaced (some people used to call it “to modify the subclasses prototype”, but I think “replacement” more image), so that a subclass Constructor on the prototype (Constructor) the value of the attribute becomes the superclass Constructor, this also is we don’t want to see, so after implementation inheritance, We need to manually modify the constructor properties of the subclass;
Sub.prototype.constructor=Sub;// Manually modify the subclass constructor pointer;
Copy the code

2.2 Call Inheritance (borrowed constructor Inheritance)

In prototype inheritance, we inherit the public and private methods of the parent class from the public and private methods of the subclass, but sometimes we don’t want to inherit both. In many cases, we just need to inherit the private methods of a class. This is where we use call inheritance.

The call method is a method that uses the this keyword, and the this constructor is an instance of the current class. So in the subclass constructor, call executes the parent class constructor (without the new keyword). Change the this keyword in the superclass constructor to this in the subclass constructor, so that the private attributes and methods of the superclass instance are inherited from the subclass instance as the superclass constructor executes. Example:

function Super(){/ / parent class
  this.delete=functinon(item){}}; Super.prototype.edit=function(){};
function Sub(){/ / subclass
  this.generation=son;
  Super.call(this);// Call inherits the core code
};
Copy the code

2.3 Hybrid Inheritance

Stereotype inheritance is to make the parent private and the public become subclass public, and call inheritance is to make the parent private become subclass private, so is there an inheritance that makes the parent public become subclass public and the parent private become subclass private? Hybrid inheritance solves this problem;

Hybrid inheritance is a mixture of stereotype and call inheritance, so that classes that are public become subclasses that are public and classes that are private become subclasses that are private. However, there is a private parent class in the public of the subclass, but the prototype search mechanism is to find the private child class first, which is not overshadowed by the defects, the advantages of hybrid inheritance is very prominent. Example:

function Super(){/ / parent class
  this.delete=functinon(item){}}; Super.prototype.edit=function(){};
Sub.prototype=new Super();// The prototype inherits core code
Sub.prototype.contructor=Sub;// Modify the constructor direction
function Sub(){/ / subclass
   this.generation=son;
   Super.call(this);// Call inherits the core code
}
Copy the code

2.4 Middleware Inheritance

Middleware inherited implementations rely on the __proto__ attribute. __proto__ on subclass prototypes refers to Object prototypes by default. We insert the parent prototype before __proto__ refers to Object.prototype. Middleware inheritance actually extends the prototype chain of the subclass. Middleware inheritance extends the parent class public to the subclass public. Example:

function Super(){/ / parent class
  this.delete=functinon(item){}}; Super.prototype.edit=function(){};
function Sub(){/ / subclass
    this.generation=son;
}
Sub.prototype.__proto__=Super.prototype;// Middleware inherits core codeNote that.__proto__ is not compatible with IE, so use it with caution;Copy the code

Extension: Implement inheritance skillfully with Object. Create (proObj) method

This inheritance approach is clever because it takes advantage of the fact that the return value of this method is an object modeled after proObj, which is implemented in the same way as middleware inheritance. But in IE8- not compatible. Example:

function Super(){/ / parent class
  this.delete=functinon(item){};
};
Super.prototype.edit=function(){};
function Sub(){/ / subclass
   this.generation=son;
};
Sub.prototype. = Object.create(Super.prototype);// Core codeAlthough the method is not compatible, I tried simple simulationObject.create method, code as followsfunction(obj){
  function Fn(){};
  Fn.prototype=obj;
  return new Fn();
};
Copy the code

The above is about object-oriented inheritance, and finally talk about object-oriented polymorphism in JS, polymorphism includes overloading and rewriting; It is important to note that overloading cannot be implemented in JS in the same way as traditional object-oriented methods. In other languages (such as Java), it is possible to write two definitions for a function, as long as the two definitions have different signatures. In a background language such as Java, it is possible to define two functions with the same name, as long as the two functions have different types or numbers of arguments. However, in JS, if you define more than one function with the same name, it will be overwritten in the pre-interpretation phase, whichever comes last. There is a phenomenon in JS that is similar to, but not overloading; Example:

function sum(num){
   if(typeofNum = = ="undefined") {return 0
}
return num++;
}
Copy the code

In the example above, the sum method is always called even though the parameters are different. In the example above, the sum method is always called even though the parameters are different. In the example above, the sum method is always called when the parameters are different.