Javascript Object-Oriented Programming (I)-encapsulation

Source: Internet
Author: User
Tags variable scope

Javascript is a very flexible object-oriented programming language, which is very different from traditional strong object-oriented programming languages (such as C ++, Java, C, therefore, to implement some features such as C ++, Java, and C #, you need to consider them in another way. Today we will mainly discuss how to encapsulate data in JavaScript scripts ).

Data encapsulation simply hides content that the caller does not want to see. It is the first of the three elements of object-oriented programming. The other two are inheritance and polymorphism, and their content will be discussed later.

Data encapsulation is implemented by using keywords such as public, private, and static in languages such as C ++, Java, and C. Javascript uses another completely different form. Before discussing how to implement data encapsulation in a specific way, let's talk about some simple JavaScript concepts that are well known but easy to ignore.

1. Several Basic Concepts
1.1 variable definition
In JavaScript, variables are defined using the VaR keyword.

However, if we assign a value to a variable that is not defined using VAR, the variable will become a global variable.

In general, we should avoid using variables not defined by VAR, mainly because it will affect the execution efficiency of the program, because the speed of accessing global variables is much slower than that of local variables.

However, this method ensures that our variables must be global variables.

In addition, to ensure speed, when using global variables, we can use VaR to define a local variable, and then assign it to the global variable to obtain a local reference of the global variable.

1.2 variable type
No variable defined. The type is undefined.

The variable value can be a function.

A function can act as a class in JavaScript.

1.3 variable scope
Variable scope refers to the valid range of the variable lifecycle.

Blocks created using {} cannot create scopes.

With adds its object scope to the current scope chain, but with does not create a new scope. After the with block ends, the object scope is deleted from the current scope chain.

In try-catch, the catch error object is valid only in the catch block, but the variables defined in the Catch Block belong to the current scope.

Blocks created by other control statements, such as if, for, for-in, while, do-while, and switch, cannot create scopes.

A function created with function will create a new scope and add it to the current scope.

2 Encapsulation
Next we will discuss the specific encapsulation. First, let's talk about several packages that you are most familiar with: Private instance members, public instance members, and public static members. At last, we will discuss the encapsulation of Private Static members and static classes that we are not familiar. This is because we will discuss object-oriented programming. When all functions are defined and used as classes, we will temporarily turn them into classes.

2.1 private instance members
Private instance members can be implemented using local variables in the function in Javascript, which is equivalent to private instance members of the class. For example:

Class1 = function (){
// Private Fields
VaR m_first = 1;
VaR m_second = 2;
// Private methods
Function Method1 (){
Alert (m_first );
}
VaR method2 = function (){
Alert (m_second );
}
// Constructor
{
Method1 ();
Method2 ();
}
}
VaR o = new class1 ();
// Error
Alert (O. m_first );
O. Method1 ();
M_first and m_second are two private instance fields of class1, and Method1 and method2 are two private instance methods. They can only be used inside the class object and cannot be used outside the class object.

Here you will find that there are two ways to create a private method. One is to define a method directly in the class, and the other is to define a local variable (Private instance field) first ), then assign an anonymous method to it.

If you define a method directly in a class, the scope of the method is this class. Therefore, this method cannot be accessed outside of this class, and it can access all private instance fields in the class, this ensures that this is a private instance method.

The second method is the same as the first method, but the second method is more flexible.

You should also note that the constructor code in class1 is included in {}. Although this is not necessary, the code looks clearer.

There are two points to note about the constructor code:

1. the constructor code must be placed at the end of the class definition to ensure that all methods called in the constructor have been defined. Because Javascript is an interpreted language, it will be executed in the order from top to bottom. Therefore, if the constructor code is placed before the definition of other methods, if the method to be called is not found when the call statement is executed, an error occurs.

2. We already know that the block created by {} will not change the scope. Therefore, if you create a local variable in such constructor code, you actually create a private instance Member in the entire class. Therefore, if you need to use local variables, you should define a private instance method. For example, you can name it Constructor () this private instance method defines the local variable and the code to be executed in the original {} constructor, and then directly calls it at the end of the class. Therefore, the better method is as follows:

Class1 = function (){
// Private Fields
VaR m_first = 1;
VaR m_second = 2;
// Private methods
Function Constructor (){
Method1 ();
Method2 ();
}
Function Method1 (){
Alert (m_first );
}
VaR method2 = function (){
Alert (m_second );
}
Constructor ();
}
VaR o = new class1 ();
// Error
Alert (O. m_first );
O. Method1 ();
Finally, you may also find that the class1 definition does not use VaR, so that we can ensure that it is a global class.

2.2 Public instance members
Public instance members can be created in two ways. Let's take a look at the following example:

Class2 = function (){
// Private Fields
VaR m_first = 1;
VaR m_second = 2;
// Private methods
Function Method1 (){
Alert (m_first );
}
VaR method2 = function (){
Alert (m_second );
}
// Public fields
This. First = "first ";
This. Second = ['s ', 'E', 'C', 'O', 'n', 'D'];
 
// Public methods
This. Method1 = method2;
 
This. method2 = function (){
Alert (this. Second );
}
 
// Constructor
{
Method1 ();
Method2 ();
}
}
// Public Method
Class1.prototype. method3 = function (){
Alert (this. First );
}
 
VaR o = new class2 ();
 
O. Method1 ();
O. method2 ();
O. method3 ();
Alert (O. First );
We found that this example is supplemented in the class1 example. The public instance field and public instance method are added to it. We call them public instance members.

We should have discovered that creating a public instance Member is actually very simple, one way is to give this. membername is used to assign values. If the value is of a type other than a function, it is a public instance field. If the value is of the function type, it is the public instance method. Another way is to assign a value to classname. Prototype. membername. The value can be of the same type as this. membername.

Is this defined, or is prototype defined?

In fact, they have their own purposes. They do not have a better relationship than others. In some cases, we can only define public instance members in a specific way, rather than using another method. The reason is that they are actually different:

1. The prototype method should only be defined outside the class. This method can only be defined in the class.

2. If prototype is defined in a class, when a private instance Member is accessed, the private instance Member in the last object instance is always accessed.

3. A public instance Member defined in prototype mode is a member created on the prototype of the class. A public instance Member defined in this mode is a member directly created on the Instance Object of the class.

Based on the two differences, we can conclude that to access private instance members in the public instance method, this must be defined.

For the third difference, we will further analyze it when discussing inheritance. You only need to know the difference here.

We will also find that the names of public and private instance members can be the same, so there will be no conflict?

Of course not. The reason is that they have different access methods. When a public instance Member accesses a class, it must be referenced with the this. prefix. When a private instance Member accesses a class, it cannot use this. prefix if it is not used. In out-of-class access, only public members can access the instance objects of the class, and Private Members cannot access the instance objects.

2.3 Public static members
The definition of public static members is very simple, for example:

Class3 = function (){
// Private Fields
VaR m_first = 1;
VaR m_second = 2;
// Private methods
Function Method1 (){
Alert (m_first );
}
VaR method2 = function (){
Alert (m_second );
}
// Constructor
{
Method1 ();
Method2 ();
}
}
 
// Public static field
Class3.field1 = 1;
 
// Public static method
Class3.method1 = function (){
Alert (class3.field1 );
}
 
Class3.method1 ();
In this example, class3 is similar to class1. The difference is that we define a static field and static method for class3.

You can assign a value to classname. membername.

The static fields and static methods defined here can be accessed directly by Class Name Reference without the need to create objects. Therefore, they are public static members.

But remember, do not define public static members within the class where they are located. Otherwise, you will get unexpected results. Let's look at the example below:

Class4 = function (){
// Private Fields
VaR m_first = 1;
VaR m_second = 2;
 
VaR s_second = 2;
 
// Private methods
Function Method1 (){
Alert (m_first );
}
VaR method2 = function (){
Alert (m_second );
}
Class4.method1 = function (){
S_second ++;
}
Class4.method2 = function (){
Alert (s_second );
}
}
VaR O1 = new class4 ();
Class4.method2 (); // 2
Class4.method1 ();
Class4.method2 (); // 3
VaR O2 = new class4 ();
Class4.method2 (); // 2
Class4.method1 ();
Class4.method2 (); // 3
In this example, we expect s_second to assume the role of a private static member, but the output result is not what we expected. We will find that s_second is actually a private instance Member of class4, rather than a private static member. The private members accessed by Method1 and method2 in class4 are always members of this private instance in the last instance object of the class.

Where is the problem?

The problem is that every time an object instance is created through new class4 (), all statements in class4 are re-executed. Therefore, s_second is reset and becomes a private instance member of the new object. Class4.method1 and class4.method2 are also redefined, and this definition also switches their variable scope to the last object. This is the same as the error caused by defining the public instance method created in prototype in the class.

Therefore, do not define public static members within the class where they are located! Do not define the public instance method created using prototype in the class!

So how to define a private static member?

2.4 Private Static members
In the previous basic concepts, we have learned that a new scope can be created only when functions are used to create functions, and private members (static members or instance members) must be created ), you must create a new scope to hide data. The following method is implemented based on this.

Private Static members are implemented by creating an anonymous function to create a new scope.

Usually, when an anonymous function is used, it is assigned to a variable and then referenced by this variable. In this case, the anonymous function can be called repeatedly or used as a class to create objects. Here, the created anonymous function does not assign a value to any variable. It is executed immediately after it is created, or is immediately instantiated as an object without assigning a value to any variable, in this case, the function itself or its instantiated objects cannot be accessed again, so its only function is to create a new scope, all local variables and functions are isolated. Therefore, these local variables and functions become the Private Static members we need. The anonymous function that is immediately executed or the anonymous function that is instantly instantiated is called a static encapsulation environment.

Next we will first look at an example of creating a class with a private static member by directly calling an anonymous function:

Class5 = (function (){
// Private Static Fields
VaR s_first = 1;
VaR s_second = 2;
 
// Private Static Methods
Function s_method1 (){
S_first ++;
}
VaR s_second = 2;
 
Function Constructor (){
// Private Fields
VaR m_first = 1;
VaR m_second = 2;
 
// Private methods
Function Method1 (){
Alert (m_first );
}
VaR method2 = function (){
Alert (m_second );
}
 
// Public fields
This. First = "first ";
This. Second = ['s ', 'E', 'C', 'O', 'n', 'D'];
 
// Public methods
This. Method1 = function (){
S_second --;
}
 
This. method2 = function (){
Alert (this. Second );
}
 
// Constructor
{
S_method1 ();
This. Method1 ();
}
}
// Public static methods
Constructor. Method1 = function (){
S_first ++;
Alert (s_first );
}
Constructor. method2 = function (){
Alert (s_second );
}
 
Return constructor;
})();
 
VaR O1 = new class5 ();
Class5.method1 ();
Class5.method2 ();
O1.method2 ();
VaR O2 = new class5 ();
Class5.method1 ();
Class5.method2 ();
O2.method2 ();
In this example

(Function (){
...
Function contructor (){
...
}
Return constructor;
})();
To create a static encapsulation environment. The actual class is defined in this environment, and the return statement is used to return the final class to the global variable class5, then we can use class5 to reference this class with static private members.

To distinguish between Private Static members and private instance members, we use the S _ prefix before Private Static members and the M _ prefix before private instance members to avoid duplicate names, therefore, you can always access Private Static members in an object.

However, this naming method is not mandatory, but recommended. A private static member can have the same name as a private instance Member, both the class constructor and the instance method defined in the class access private instance members, in the static method (whether public static method or Private Static Method) are all Private Static members.

A public instance method defined by prototype is a private static member outside the class and in a static encapsulation environment.

Public static methods defined outside the static encapsulation environment and public instance methods defined by prototype cannot directly access Private Static members.

Another method is to create a class with Private Static members by directly instantiating an anonymous function. The example below is similar:

New Function (){
// Private Static Fields
VaR s_first = 1;
VaR s_second = 2;
 
// Private Static Methods
Function s_method1 (){
S_first ++;
}
VaR s_second = 2;
 
Class6 = function (){
// Private Fields
VaR m_first = 1;
VaR m_second = 2;
 
// Private methods
Function Method1 (){
Alert (m_first );
}
VaR method2 = function (){
Alert (m_second );
}
 
// Public fields
This. First = "first ";
This. Second = ['s ', 'E', 'C', 'O', 'n', 'D'];
 
// Public methods
This. Method1 = function (){
S_second --;
}
 
This. method2 = function (){
Alert (this. Second );
}
 
// Constructor
{
S_method1 ();
This. Method1 ();
}
}
// Public static methods
Class6.method1 = function (){
S_first ++;
Alert (s_first );
}
Class6.method2 = function (){
Alert (s_second );
}
};
 
VaR O1 = new class6 ();
Class6.method1 ();
Class6.method2 ();
O1.method2 ();
VaR O2 = new class6 ();
Class6.method1 ();
Class6.method2 ();
O2.method2 ();
The result of this example is the same as that created in the first method. However, its static encapsulation environment is as follows:

New Function (){
...
};
Here, the function does not return values, and the class5 definition is implemented directly in the static encapsulation environment by assigning values to a variable without the VaR definition.

Of course, you can also

(Function (){
...
})();
In this way, without defining the return value for the function, the class with Private Static members can be defined directly in the static encapsulation environment by assigning values to a variable without the VaR definition.

The two methods are equivalent here.

2.5 static class
The so-called static class is a class that cannot be instantiated and only contains static members.

In JavaScript, we can directly instantiate an object of an anonymous function to implement static classes. For example:

Class7 = new function (){
// Private Static Fields
VaR s_first = 1;
VaR s_second = 2;
// Private Static Method
Function Method1 (){
Alert (s_first );
}
// Public static method
This. Method1 = function (){
Method1 ();
Alert (s_second );
}
}
Class7.method1 ();
You will find that class7 is actually an object, but this object belongs to an anonymous class. This class cannot be used after the Class 7 object is created. Class7 is not a function, so it cannot be instantiated as a class. Therefore, it is equivalent to a static class.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.