We know that JS is object-oriented. When talking about object-oriented, it is inevitable to involve the concept of classes. Generally, strongly typed languages like C# and Java have fixed syntax for defining classes. The difference with JS is that it can use various methods to implement its own classes and objects. There are several general implementation methods:
1. Factory method
The factory method refers to creating a factory function that returns a specific object type. The sample code is as follows:
function createCar(sColor,iDoors,iMpg)
{
var oTempCar=new Object;
oTempCar.color=sColor;
oTempCar.doors=iDoors;
oTempCar.mpg=iMpg;
oTempCar.showColor=function()
{
alert(this.color);
}
return oTempCar;
}
var oCar1=createCar("red",4,23);
var oCar2=createCar("blue", 3,25);
oCar1.showColor();
oCar2.showColor();
Every time its factory function is called in this way, a new object will be created. But the problem is that every time a new object is generated, a new function showColor must be created, which makes each object have its own version of showColor. In fact, all objects share the same function. To solve this problem, developers The method of the object is defined outside the factory function, and then the object is given a pointer pointing to this function, as follows
function showColor()
{
alert(this.color);
}
function createCar(sColor,iDoors,iMpg)
{
var oTempCar=new Object;
oTempCar.color=sColor;
oTempCar.doors=iDoors;
oTempCar.mpg=iMpg;
oTempCar.showColor=showColor;
return oTempCar;
}
var oCar1=createCar("red",4,23);
var oCar2=createCar("blue",3,25);
oCar1.showColor();
oCar2. showColor();
This way you don’t need to create your own showColor function for each object, but just create a pointer to this function. This solves the problem functionally, but the function does not Like object methods. Thus, the constructor method was introduced.
2. Constructor method
The constructor is very similar to the factory function. The sample code is as follows:
function Car(sColor,iDoors,iMpg)
{
this.color=sColor;
this.doors=iDoors ;
this.mpg=iMpg;
this.showColor=function()
{
alert(this.color);
}
}
var oCar1=new Car ("red",4,23);
var oCar2=new Car("blue",3,25);
In the constructor, there is no object created internally, but using this keyword. When calling the constructor using the new operator, an object is created before executing the first line of code. This object can only be accessed using this. But what's the problem with this? Obviously, each of its objects will also create its own version of the showColor function. In order to solve this problem, the following prototype method is introduced.
3. Prototype method
This method makes use of the prototype attribute of the object, which can be regarded as the basis for creating new objects. prototype. Here, an empty constructor is used to set the class name. Then assign all methods and properties directly to the prototype attribute. As follows:
function Car()
{}
Car.prototype.color="red";
Car.prototype.doors=4;
Car.prototype.mpg=23;
Car.prototype.drivers=new Array("Mike", "Sue");
Car.prototype.showColor=function()
{
alert(this.color);
}
The prototype method can only assign values directly, and cannot initialize the value of the property by passing parameters to the constructor. When using this method, you will encounter two problems. I don’t know if you have noticed it. The first problem is that with this approach you must create each object before you can change the default value of the property. Rather than creating each object, you cannot directly have the attribute values you need. This is annoying. The second problem is when the attribute refers to an object. There are no problems with function sharing, but there are problems with object sharing. Because each instance generally implements its own object.
as follows:
var oCar1= new Car();
var oCar2=new Car();
oCar1.drivers.push("Matt");
alert(oCar1.drivers);//Output "Mike,Sue,Matt"
alert(oCar2.drivers);//Output "Mike, Sue, Matt"
Therefore, the drivers attribute is just a pointer to the object, so all instances actually share the same object. Because of these problems, we introduced the following method of jointly using constructors and prototypes.
4. Mixed constructor/prototype approach
The idea of this approach is to use the constructor to define all non-function properties of the object (including ordinary properties and properties pointing to the object) , define the function attributes (methods) of the object in a prototype manner. The result is that all functions are created only once, and each object has its own object property instance. The sample code is as follows:
function Car(sColor,iDoors,iMpg )
{
this.color=sColor;
this.doors=iDoors;
this.mpg=iMpg;
this.drivers=new Array("Mike","Sue") ;
}
Car.prototype.showColor=function()
{
alert(this.color);
}
var oCar1=new Car("red",4, 23);
var oCar2=new Car("blue",3,25);
oCar1.drivers.push("Matt");
alert(oCar1.drivers);//Output "Mike ,Sue,Matt"
alert(oCar2.drivers);//Output "Mike,Sue"
As can be seen from the example code, this method solves the two problems of the previous method at the same time question. However, some developers still feel that this approach is not perfect.
5. Dynamic prototype method
We know that most object-oriented languages have visually encapsulated properties and methods. However, the showColor method in the above method is defined outside the class. Therefore, they designed a dynamic prototyping approach. The basic idea of this approach is the same as the hybrid constructor/prototype approach, the only difference is the location of the object methods. As shown below:
function Car(sColor,iDoors,iMpg )
{
this.color=sColor;
this.doors=iDoors;
this.mpg=iMpg;
this.drivers=new Array("Mike","Sue") ;
if(typeof Car._initialized=="undefined")
{
Car.prototype.showColor=function()
{
alert(this.color);
}
}
Car._initialized=true;
}
In this way Car.prototype.showColor is only created once. With this dependency, this code becomes more like a class definition in other languages.
6. Mixed factory method
This method is usually a workaround for the previous method. Its purpose is to create fake constructors that just return a new instance of another kind of object.
function createCar()
{
var oTempCar=new Object;
oTempCar.color=“red”;
oTempCar.doors=4;
oTempCar.mpg=23;
oTempCar.showColor=function()
{
alert(this.color);
};
return oTempCar;
}
var car=new Car();
Because in the Car() constructor The new operator is called internally, so the second new operator is automatically ignored. The object created inside the constructor is passed back to the variable var. This approach has the same problems as the classic approach regarding the internal management of object methods. Therefore, it is strongly recommended to avoid using this method unless absolutely necessary.