How to Write maintainable oo JavaScript code
Ability to write maintainable object-oriented JavascriptCodeIt not only saves money, but also makes you very popular. Believe it? Maybe you or someone else will come back to reuse your code one day. If you try to make this experience less painful, you can save a lot of time. Everyone on Earth knows that time is money. In the same way, you will gain a preference for someone because it saves them a headache. However, before you start to explore how to write maintainable object-oriented JavaScript code, let's take a quick look at what object-oriented code is. If you already know the concept of object-oriented, you can skip the next section.
What Is Object-Oriented?
Object-Oriented Programming mainly uses code to represent real objects in the real world. To create an object, you must first define it by writing a "class. Classes can represent almost everything: Accounts, employees, navigation menus, cars, plants, advertisements, drinks, and so on. Each time an object is created, an object is instantiated from the class. In other words, it is to create a class instance as an object. In fact, objects are usually used to process more than one similar thing. In addition, you only need a simple functionProgramYou can do well. Objects are essentially data containers. Therefore, in an employee object, you may need to store employee numbers, names, employment dates, titles, salaries, qualifications, and so on. Objects also include functions that process data (also called methods "). Methods are used as media to ensure data integrity and convert data before storage. For example, a method can receive dates in any format and convert them to a standard format before they are stored. Finally, the class can inherit other classes. Inheritance allows you to reuse the same code in different classes. For example, both a bank account and an audio and video store account can inherit a basic account type, including personal information, account opening date, and branch information. Then, each user can define their own transaction or loan processing data structures and methods.
Warning JavaScript object-oriented is different
The previous section outlines the basic knowledge of classical object-oriented programming. The typical reason is that JavaScript does not follow these rules. On the contrary, JavaScript classes are written as functions, while inheritance is implemented through prototype. Prototype inheritance basically means using prototype attributes to inherit objects, rather than inheriting classes from classes.
Object Instantiation
The following is an example of Object Instantiation in javascript:
//Define the employee class
FunctionEmployee (Num, fname, lname ){
This. Getfullname =Function(){
ReturnFname + "" + lname;
}
};
//Instantiate an employee object
VaRJohn =NewEmployee ("4815162342", "John", "doe ");
Alert ("the employee's full name is" + John. getfullname ());
Here, there are three important points to note:
1. The first letter of the "class" function name must be in uppercase. This indicates that the function is instantiated rather than called as a common function.
2. The new operator is used for instantiation. If new is omitted and function calling is performed only, many problems may occur.
3. Because getfullname is specified to this operator, it is public and available, but fname and lname are not. The closure generated by the employee function gives the getfullname entry to fname and lname, but it is still private to other classes.
Prototype inheritance
The following is an example of original type inheritance in javascript:
// Define human class
Function Human (){
This . Setname = Function (Fname, lname ){
This . Fname = fname;
This . Lname = lname;
}
This . Getfullname = Function (){
Return This . Fname + "" + This . Lname;
}
}
// Define the employee class
Function Employee (Num ){
This . Getnum = Function (){
Return Num;
}
};
// Let the employee inherit the human class
Employee. Prototype = New Human ();
// Instantiate an employee object
VaR John = New Employee ("4815162342 ");
John. setname ("John", "doe ");
Alert (John. getfullname () + "'s employee number is" + John. getnum ());
This time, the created human class contains all the common attributes of humans-I also put fname and lname, because not only employees have names, but all people have names. Then assign the human object to its prototype attribute.
Code reuse through inheritance
In the previous example, the original employee class is divided into two parts. All common human attributes are moved to the human class, and the employee inherits the human class. In this way, attributes in human can be used by other objects, such as student, client, citizen, and visitor. Now you may have noticed that this is a good way to separate and reuse code. When processing a human object, you only need to inherit the human object to use the existing attributes, instead of re-creating each different object. In addition, if you want to add an "Intermediate name" attribute, you only need to add it once. Those that inherit the human class can be immediately used. Instead, if we just want to add the "Intermediate name" attribute to an object, we can add it directly to that object without adding it to the human class.
Public and private)
Next, I want to talk about public and private variables in the class. Data is processed as private or public based on the data processing methods in the object. Private attributes do not necessarily mean that others cannot access them. It may only be required for a method.
Read-Only
Sometimes, you just want to have a value when creating an object. Once created, no one else needs to change the value. To do this, you can create a private variable and assign values to it during instantiation.
FunctionAnimal (type ){
VaRData = [];
Data ['type'] = type;
This. GetType =Function(){
ReturnData ['type'];
}
}
VaRFluffy =NewAnimal ('Dog ');
Fluffy. GetType ();//Return 'Dog'
In this example, a local array data is created in the animal class. When an animal object is instantiated, a type value is passed and placed in the data array. Because it is private, this value cannot be overwritten (the animal function defines its range ). Once the object is instantiated, the only way to read the type value is to call the GetType method. Because GetType is defined in animal, with the closure generated by animal, GetType can be imported into data. In this way, the type of the object can be read but cannot be changed.
It is very important that when an object is inherited, the "read-only" technology cannot be used. After inheritance is executed, each instantiated object shares the read-only variables and overwrites their values. The simplest solution is to convert the read-only variables in the class to public variables. However, you must keep them private. You can use the technology mentioned in the comment by Philip.
Public)
Of course, sometimes you want to read or write the value of an attribute at will. To achieve this, you need to use the this operator.
FunctionAnimal (){
This. Mood = '';
}
VaRFluffy =NewAnimal ();
Fluffy. Mood = 'Happy ';
Fluffy. mood;//Return 'Happy'
This time, the animal class discloses a mood attribute that can be read and written at will. Similarly, you can specify a function to a public attribute, for example, the GetType function in the previous example. Do not assign values to GetType. Otherwise, you will destroy it.
Completely private
Finally, you may find that you need a fully private local variable. In this way, you can use the same pattern as in the first example without creating a public method.
FunctionAnimal (){
VaRSecret = "you'll never know! "
}
VaRFluffy =NewAnimal ();
Flexible API writing
Since we have already talked about the creation of classes, we need to keep the code out of date to keep pace with changes in product requirements. If you have already done some projects or have maintained a product for a long time, you should know that the demand is changing. This is an indisputable fact. If you don't think so, your code will be ruined before it is written. You may suddenly need to make the content in the tab into an animation, or you need to call Ajax to obtain data. Although it is unlikely to accurately predict the future, it is completely possible to write code flexibly for future needs.
Saner parameter list
The code can be proactive when designing the parameter list. The parameter list is the main touchpoint for others to implement your code. If it is not well designed, it will be very problematic. You should avoid the following parameter list:
FunctionPerson (employeeid, fname, lname, tel, fax, email, email2, DOB ){
};
This class is very fragile. If you want to add an intermediate name parameter after you release the code, you have to add it at the end of the list due to order problems. This makes your work awkward. If you do not assign values to each parameter, it will be very difficult. For example:
VaRAra =NewPerson (1234, "Ara", "pehlivanian", "514-555-1234 ",Null,Null,Null,
"1976-05-17 ");
You can use this mode to make the operation parameter list more clean and flexible:
FunctionPerson (employeeid, data ){
};
The first parameter is required. The rest will be mixed in the object so that it can be used flexibly.
VaRAra =NewPerson (1234 ,{
Fname: "Ara ",
Lname: "pehlivanian ",
Tel: "514-555-1234 ",
DOB: "1976-05-17"
});
The beauty of this model is that it is easy to read and highly flexible. Note that fax, email, and email2 are completely ignored. In addition, the object has no specific order, so it is very easy to add an intermediate name parameter wherever it is convenient:
VaRAra =NewPerson (1234 ,{
Fname: "Ara ",
Mname: "Chris ",
Lname: "pehlivanian ",
Tel: "514-555-1234 ",
DOB: "1976-05-17"
});
The code in the class is not important, because the values in the class can be accessed through indexes:
FunctionPerson (employeeid, data ){
This. Fname = data ['fname'];
};
If data ['fname'] returns a value, it is set. Otherwise, it is not set and there is no loss.
Code embedding
As time passes, product requirements may have more requirements for your behaviors. This behavior is not related to your core functions. It may also be the only Implementation of the class. For example, when the Panel of an option card obtains the external data of another tab, the content in this tab panel is grayed out. You may want to put these functions in the class, but they do not belong to it. The responsibility of a tab bar is to manage tabs. Animation and data retrieval are completely different. They must also be separated from the tab bar code. The only way to get your tab entries out of those additional features is to allow the rows to be embedded into the code. In other words, create events to hook them to critical moments in your code, such as ontabchange, aftertabchange, onshowpanel, and aftershowpanel. In that case, they can easily hook up with your onshowpanel event and write a processor that will gray the panel content, so that everyone will be happy. The javascript library allows you to easily do this, but it is not that difficult to write it yourself. The following is an example of using Yui 3.
<SCRIPT type = "text/JavaScript" src = "http://yui.yahooapis.com/combo? 3.2.0/build/
Yui/yui-min.js "> </SCRIPT>
<SCRIPT type = "text/JavaScript">
Yui (). Use ('event ', Function (Y ){
Function Tabstrip (){
This . Showpanel = Function (){
This . Fire ('onshowpanel ');
// Display Panel code
This . Fire ('aftershowpanel ');
};
};
// Empower tabstrip to stimulate common events
Y. augment (tabstrip, Y. eventtarget );
VaR TS =New Tabstrip ();
// Create a common time processor for this tabstrip instance
TS. On ('onshowpanel ', Function (){
// What to do before presenting the Panel
});
TS. On ('onshowpanel ', Function (){
// Other things to do before presenting the Panel
});
TS. On ('aftershowpanel ', Function (){
// What to do after the display panel
});
TS. showpanel ();
});
</SCRIPT>
In this example, there is a simple tabstrip class with a showpanel method. This method inspires two events: onshowpanel and aftershowpanel. This capability is implemented by extending the class with Y. eventtarget. Once made, we instantiate a tabstrip object and allocate a bunch of processors to it. This is the only action that is used to process instances and can avoid confusion with common code of the current class.
Summary
If you want to reuse code, whether on the same webpage, on the same website or across projects, consider packaging and organizing the code in the class. Object-oriented JavaScript naturally helps to better organize and reuse code. In addition, you can make sure that the code is flexible enough to continue using it for a long time after you finish writing the code. Writing reusable and obsolete JavaScript code can save you time and money for your team. This will definitely make you very popular.