Home >Web Front-end >JS Tutorial >javascript object-oriented new understanding of data encapsulation_js object-oriented

javascript object-oriented new understanding of data encapsulation_js object-oriented

WBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWB
WBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOriginal
2016-05-16 18:40:21969browse

Today we mainly discuss how to implement data encapsulation in JavaScript scripts.
Data encapsulation simply means hiding content that you don’t want the caller to see. It is the first of the three elements of object-oriented programming. The other two are inheritance and polymorphism. They will be discussed later.
Regarding the implementation of data encapsulation, it is implemented through keywords such as public, private, and static in C, Java, C# and other languages. In JavaScript, it takes a completely different form. Before discussing how to specifically implement a certain form of data encapsulation, let's first talk about a few simple JavaScript concepts that are well-known but easily overlooked.
1 Several basic concepts
1.1 Variable definition
In JavaScript language, variables are defined through the var keyword.
But if we directly assign a value to a variable that is not defined using var, then this variable will become a global variable.
In general, we should avoid using variables that are not defined with var. The main reason is that it will affect the execution efficiency of the program, because accessing global variables is much slower than local variables.
But this usage can ensure that our variables must be global variables.
In addition, in order to ensure speed, when we use global variables, we can define a local variable through var and then assign the global variable to it, so that we can get a local reference of the global variable.
1.2 Variable type
Undefined variables have type undefined.
The value of a variable can be a function.
Function can act as a class in JavaScript.
1.3 Variable scope
Variable scope refers to the effective scope of the variable life cycle.
Blocks created simply with { } cannot create scopes.
with adds the scope of the object it contains to the current scope chain, but with does not create a new scope. After the with block ends, the object scope is removed from the current scope chain.
In try-catch, the error object of catch is only valid 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, switch, etc. cannot create scopes.
A function created with function will create a new scope and add it to the current scope.
2 Encapsulation
Let’s discuss the specific encapsulation. First, let’s talk about the most familiar encapsulations: private instance members, public instance members and public static members. Finally, we will discuss the encapsulation methods of private static members and static classes that are unfamiliar to everyone. Because what we are going to discuss below is object-oriented programming, when functions are defined and used as classes, we will temporarily call them classes.
2.1 Private instance members
Private instance members in JavaScript can actually be implemented using local variables within functions, which are equivalent to private instance members of a class. For example:

Copy code The code is as follows:

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();

Here m_first and m_second are two private instance fields of class1, method1 and method2 are two private instance methods. They can only be used inside objects of this class and cannot be used outside objects.
Here you will find that there are two ways to create a private method, one is to define the method directly in the class, the other is to first define a local variable (private instance field), and then define an anonymous method to assign a value to it.
If you define a method directly in a class, the scope of the method is this class, so this method cannot be accessed outside this class, and it can access all private instance fields in the class, which guarantees This is a private instance method.
The second way to create a private instance method has the same effect as the first way, but the second way is more flexible.
You should also notice that the constructor code in class1 is enclosed in { }. Although this is not necessary, the code looks clearer.
There are two points that need to be explained about this constructor code:
1. The constructor code must be placed at the end of the entire class definition. This is to ensure that all methods called in it have been is defined. Because JavaScript is an interpreted language, it will be executed in order from top to bottom. Therefore, if the constructor code is placed in front of other method definitions, the method to be called will not be found when the calling statement is executed. Something went wrong.
2. We already know that the block created by { } will not change the scope, so if you create a local variable in such a constructor code, you are actually creating a private instance member in the entire class, so if you need to use For local variables, a private instance method should be defined, for example, it can be named constructor(). In the private instance method of constructor(), define the local variables and the code to be executed in the original { } constructor, and then call it directly at the end of the class. That's it. So a better way to write it is like this:
Copy the code The code 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 we do not use var in the definition of class1. This way 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 look at the following example first:
Copy code The code is as follows:

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 makes some additions to the class1 example. Public instance fields and public instance methods are added to it, and we call them public instance members.
We should have discovered that creating a public instance member is actually very simple. One way is to assign a value to this.memberName in the class. If the value is a type other than a function, it is a public instance field. If the value is Function type, that is the public instance method. Another way is to assign a value to className.prototype.memberName. The assignable type is the same as this.memberName.
Should it be defined through this method or through prototype method?
In fact, they each have their own uses, and the relationship between them is not that one is better than the other. In some cases, we can only define public instance members in one specific way, but not the other. 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 a class.
2. If the prototype method is defined in a class, when accessing private instance members, the private instance members in the last object instance will always be accessed.
3. Public instance members defined in prototype mode are members created on the prototype of the class. Public instance members defined in this method are members created directly on the instance object of the class.
Based on the first two differences, we can draw the conclusion that if you want to access private instance members in a public instance method, you must use this method to define it.
Regarding the third difference, we will analyze it more deeply when we discuss inheritance later. All you need to know here is this difference.
We will also find that the names of public instance members and private instance members can be the same. Will there be no conflict?
Of course not. The reason is that their access methods are different. When public instance members are accessed in a class, they must be referenced with this. prefix. When private instance members are accessed in a class, they do not and cannot use this. prefix to access them. When accessing outside the class, only public members can be accessed through the instance object of the class, and private members cannot be accessed.
2.3 Public static members
The definition of public static members is very simple, for example:
Copy code The code is as follows:

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();

The class3 of this example is the same as class1 is very similar. The difference is that outside class3, we have defined a static field and static method for class3.
The way to define it is to directly assign a value to className.memberName.
The static fields and static methods defined here can be accessed directly through class name references without creating objects. Therefore they are public static members.
But one thing to remember is that you must not define public static members inside the class where they are located, otherwise you will get results that are not what you expect. We can look at the following example:
Copy code The code is as follows:

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 play the role of a private static member, but the output is not what we expect. We will find that s_second is actually a private instance member of class4, not a private static member. The private members accessed by method1 and method2 of class4 are always the private instance members in the last instance object of the class.
What’s the problem?
The problem is that every time an object instance is created through new class4(), all statements in class4 are re-executed, so s_second is reset and becomes a private instance member in the new object. Class4.method1 and class4.method2 have also been redefined, and this definition also switches their variable scope to the last object. This is the same error that occurs when a public instance method created through prototype is defined inside a class.
So, be sure not to define public static members inside the class in which they are located! Don't define public instance methods created through prototype method inside the class!
How to define a private static member?
2.4 Private static members
We have already understood in the basic concept that only by using function to create a function can we create a new scope. To create a private member (whether it is a static member or an instance member), It is necessary to create a new scope to achieve the purpose of data hiding. The method adopted below is based on this point.
Implementing private static members is achieved by creating an anonymous function to create a new scope.
Usually when we use an anonymous function, we assign it to a variable and then reference the anonymous function through this variable. In this case, the anonymous function can be called repeatedly or the object can be created as a class. And here, the anonymous function we created is not assigned to any variable and is executed immediately after it is created, or is instantiated as an object and the object is not assigned to any variable. In this case, the function itself or its instance The transformed object cannot be accessed again, so its only function is to create a new scope and isolate all local variables and functions inside it. Therefore, these local variables and functions become the private static members we need. We call this immediately executed anonymous function or immediately instantiated anonymous function a static encapsulation environment.
Let’s first look at an example of creating a class with private static members by directly calling anonymous functions:
Copy code The code is as follows:

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;
New JavaScript object-oriented training (2)
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, through
(function() {
...
function contructor () {
...
}
return constructor;
})();


to create a static encapsulation environment, the actual class is defined in this environment, and at the end, the final class is returned to our global variable class5 through the return statement, and then we can reference this band through class5 A class with static private members.
In order to distinguish private static members from private instance members, we use the s_ prefix in front of the private static members and the m_ prefix in front of the private instance members. This avoids duplication of names, so private objects can always be accessed in the object. Static member.
However, this naming method is not necessary, but only recommended. Private static members can have the same name as private instance members. In the case of duplicate names, they can be accessed in the class constructor and instance methods defined in the class. It is a private instance member, and all accessed in static methods (whether public static methods or private static methods) are private static members.
Public instance methods defined through prototype outside the class and in a static encapsulation environment access private static members.
Public static methods defined outside the static encapsulation environment and public instance methods defined through prototype cannot directly access private static members.
Another way to create a class with private static members by directly instantiating anonymous functions is very similar to the above example:
Copy code The code is as follows:

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 the example created through the first method. It’s just that its static encapsulation environment is like this:
new function() {
...
};
Here, the function has no return value, and the definition of class5 is directly in The static encapsulation environment is implemented internally by assigning a value to a variable that is not defined with var.
Of course, you can also use
(function() {
...
})();
without defining a return value for the function, but directly The static encapsulation environment implements the definition of a class with private static members by assigning a value to a variable that is not defined with var.
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 implement a static class by directly instantiating an anonymous function object. For example:
Copy code The code is as follows:

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 can no longer be used after the class7 object is created. Class7 is not a function, so it cannot be instantiated as a class. Therefore, it is equivalent to a static class here.
Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn