In-depth understanding of the JavaScript series (17): Introduction to object-oriented programming _ basic knowledge

Source: Internet
Author: User
Tags prototype definition traits
This article mainly introduces a deep understanding of the JavaScript series (17): An Introduction to object-oriented programming, this article describes the introduction, paradigm and ideas, class-based features and prototype-based, static-based, and hierarchical inheritance. For more information, see Introduction

In this article, we will consider various aspects of object-oriented programming in ECMAScript (although this topic has been discussed in many previous articles ). We will look at these problems more theoretically. In particular, we will consider the object creation algorithm and the relationship between objects (including basic relationships-inheritance, it can also be used in the discussion (I want to eliminate some previous conceptual ambiguity about OOP in JavaScript ).

Http://dmitrysoshnikov.com/ecmascript/chapter-7-1-oop-general-theory/.

Overview, paradigm and thoughts

Before analyzing OOP Technology in ECMAScript, it is necessary to master some basic features of OOP and clarify the main concepts in the overview.

ECMAScript supports structured, object-oriented, functional, and imperative programming methods. In some cases, it also supports Aspect-Oriented Programming, therefore, the definition of object-oriented programming in ECMAScript is given:

ECMAScript is a prototype-based object-oriented programming language.
There are many differences between prototype-based OOP and static classes. Let's take a look at their detailed differences.

Class-based features and prototype-based

Note: The important point in the previous sentence is that it is completely based on static classes. With the word "static", we understand static objects and static classes, which are strongly typed (although not required ).

Many documents on the Forum have stressed that this is the main reason for their opposition to comparing classes and prototypes in JavaScript, although their implementations are different (for example, Python and Ruby Based on Dynamic classes), they are not too opposed to the focus (some conditions are written, although their thoughts are somewhat different, but JavaScript has not become so alternative), but they are opposed to static classes and dynamic prototypes (statics + classes. dynamics + prototypes), specifically, a static class (for example, C ++, JAVA) the mechanism of its subordinates and method definition allows us to see the exact difference between it and prototype-based implementation.

However, let's list them one by one. Let us consider the general principles and the main concepts of these paradigms.

Based on static classes

In the class-based model, there is a concept about classes and instances. Class instances are often named as objects or examples.

Class and Object

Class represents the abstraction of an instance (that is, an object. This is a bit like mathematics, but we call it type or classification ).

For example (here and below are both pseudo code ):

The Code is as follows:


C = Class {a, B, c} // Class C, including features a, B, c


The instance features attributes (Object Description) and methods (Object activity ). The feature itself can also be regarded as an object: whether the attribute is writable, configurable, and configurable (getter/setter. Therefore, the object stores the state (that is, the specific values of all attributes described in a class), and the class defines a strictly unchanged structure (attribute) for their instances) and Strictly unchanged behavior (method ).

The Code is as follows:


C = Class {a, B, c, method1, method2}

C1 = {a: 10, B: 20, c: 30} // Class C is an instance: Object lifecycle 1
C2 = {a: 50, B: 60, c: 70} // Class C is an instance: Object lifecycle 2, with its own status (that is, the attribute value)

Hierarchy inheritance

To improve code reuse, classes can be extended from one to another with additional information added. This mechanism is called hierarchy inheritance.

The Code is as follows:


D = Class extends C = {d, e} // {a, B, c, d, e}
D1 = {a: 10, B: 20, c: 30, d: 40, e: 50}

When the caller is on the instance of the class, the native class book usually finds this method. If the method is not found, the parent class is directly searched. If the method is not found, find the parent class of the parent class (such as the strict inheritance chain). If the top of the inheritance class is not found, the result is: the object has no similar behavior, you cannot obtain the results.

The Code is as follows:


D1.method1 () // D. method1 (no)-> C. method1 (yes)
D1.method5 () // D. method5 (no)-> C. method5 (no)-> no result


Compared to copying methods in inheritance to a subclass, attributes are always complicated in the subclass. We can see that subclass D inherits from the parent class C: Attributes a, B, and c are copied, and the structure of D is {a, B, c, d, e }}. However, the method {method1, method2} does not copy the past, but inherits the past. Therefore, if a very deep-level class has attributes that are not required by objects at all, the subclass also has these attributes.

Key concepts of class-based

Therefore, we have the following key concepts:

1. Before creating an object, you must declare a class. First, you must define its class.
2. Therefore, this object will be created from the class abstracted into its own "pictogram and similarity" (structure and behavior)
3. The method is handled through a strict, direct, and unchanging inheritance chain.
4. Subclass contains all attributes of the inheritance chain (even if some attributes are not required by the subclass );
5. Create a class instance. The class cannot (because of the static model) change its instance features (attributes or methods );
6. An Instance (because of its strict static model) does not have any additional behaviors or attributes except the behaviors and attributes declared in the corresponding class of the instance.

Let's take a look at how to replace the OOP model in JavaScript, that is, the prototype-based OOP we suggest.

Prototype-based
The basic concept here is dynamic variable objects. Conversion (complete conversion includes not only values, but also features) is directly related to dynamic languages. The following objects can independently store all their features (attributes, methods) without the need for classes.

The Code is as follows:


Object = {a: 10, B: 20, c: 30, method: fn };
Object. a; // 10
Object. c; // 30
Object. method ();

In addition, due to the dynamic nature, they can easily change (add, delete, and modify) their own features:

The Code is as follows:


Object. method5 = function () {...}; // Add a new method
Object. d = 40; // Add the new property "d"
Delete object. c; // delete the attribute "deleted"
Object. a = 100; // modify the attribute "Hangzhou"

// The result is: object: {a: 100, B: 20, d: 40, method: fn, method5: fn };

That is to say, when assigning values, if some features do not exist, create them and initialize them. If they exist, they are only updated.

In this case, code reuse is not implemented through the extension class. (Note that the class cannot be changed because there is no class concept here ), it is implemented through prototype.

A prototype is an object that is used as the original copy of other objects. If some objects do not have their own necessary features, the prototype can be used as a delegate of these objects as a secondary object.

Based on Delegation

Any object can be used as the prototype object of another object, because the object can easily change its prototype dynamics at runtime.

Note that we are currently considering the introduction rather than the specific implementation. when we discuss the specific implementation in ECMAScript, we will see some of their own characteristics.

Example (pseudo code ):

The Code is as follows:


X = {a: 10, B: 20 };
Y = {a: 40, c: 50 };
Y. [[Prototype] = x; // x is the Prototype of y.

Y. a; // 40, its own characteristics
Y. c; // 50, which is also a feature
Y. B; // 20-obtain from the Prototype: y. B (no)-> y. [[Prototype]. B (yes): 20

Delete y. a; // delete its own "deleted"
Y. a; // 10-Get from prototype

Z = {a: 100, e: 50}
Y. [[Prototype] = z; // modify the Prototype of y to z.
Y. a; // 100-Get from prototype z
Y. e // 50, also obtained from prototype z

Z. q = 200 // Add a new property to the prototype
Y. q // The modification also applies to y

This example shows the prototype as an important feature and mechanism of the Secondary object attributes. It is like you need your own attributes. Compared with your own attributes, these attributes are delegated attributes. This mechanism is called delegation and its prototype model is a prototype of delegation (or a prototype based on delegation ). The reference mechanism is called sending information to an object here. If this object does not receive a response, it will be delegated to the prototype for search (requiring it to try to respond to the message ).

In this case, code reuse is called delegate-based inheritance or prototype-based inheritance. Because any object can be used as a prototype, the prototype can also have its own prototype. These prototypes are connected together to form a so-called prototype chain. A link is also hierarchical in a static class, but it can be easily rearranged to change the hierarchy and structure.

The Code is as follows:


X = {a: 10}

Y = {B: 20}
Y. [[Prototype] = x

Z = {c: 30}
Z. [[Prototype] = y

Z. a // 10

// Z. a is found in the prototype chain:
// Z. a (no)->
// Z. [[Prototype]. a (no)->
// Z. [[Prototype]. [[Prototype]. a (yes): 10

If an object and its prototype chain cannot respond to message sending, the object can activate the corresponding system signal, which may be processed by other delegation on the prototype chain.

This system signal is available in many implementations, including dynamic systems: # doesNotUnderstand in Smalltalk, method_missing in Ruby, and _ getattr __in Python __, implement _ call; in PHP and _ noSuchMethod _ in ECMAScript, and so on.

Example (implementation of ECMAScript of SpiderMonkey ):

The Code is as follows:


Var object = {

// Catch the system signal that cannot respond to the message
_ NoSuchMethod __: function (name, args ){
Alert ([name, args]);
If (name = 'test '){
Return '. test () method is handled ';
}
Return delegate [name]. apply (this, args );
}

};

Var delegate = {
Square: function (){
Return a *;
}
};

Alert (object. square (10); // 100
Alert (object. test (); //. test () method is handled

That is to say, based on the implementation of static classes, when the message cannot be responded, the conclusion is: the current object does not have certain features, but if you try to get from the prototype chain, it is still possible to get results, or the object has this feature after a series of changes.

The specific implementation of ECMAScript is to use a delegation-based prototype. However, as we will see from the specifications and implementations, they also have their own characteristics.

Concatenative Model

To be honest, it is necessary to say something about another situation (not used in ECMASCript as soon as possible): When the prototype is complicated from other objects, the original replaces the native object. In this case, code reuse refers to the real copying (cloning) of an object during the object creation stage, rather than the delegation. This prototype is called concatenative prototype. Copying all prototype features of an object can further completely change its attributes and methods, and can also change itself as a prototype (in a delegate-based model, this change does not change the existing object behavior, but changes its prototype features ). The advantage of this method is that it can reduce the scheduling and delegation time, but the disadvantage is the memory usage.

Duck type

Returning an object with a dynamic weak type change is not related to the type (class) of the object, compared with a static class-based model, it is necessary to check whether the message is related ).

For example:

The Code is as follows:


// In a static-based model
If (object instanceof SomeClass ){
// Some actions are running
}

// In dynamic implementation
// What type the object is at this time is not important
// Mutations, types, and features can be changed freely and repeatedly.
// Whether important objects can respond to the test message
If (isFunction (object. test) // ECMAScript

If object. respond_to? (: Test) // Ruby

If hasattr (object, 'test'): // Python

This is the so-called Dock type. In other words, objects can be identified by their own characteristics during check, rather than the position of objects in the hierarchy or they belong to any specific type.

Prototype-based Key Concepts

Let's take a look at the main features of this method:

1. The basic concept is the object.
2. The object is completely dynamic (theoretically, it can be converted from one type to another)
3. The object does not have a strict class to describe its own structure and behavior, and the object does not need a class.
4. objects do not have class classes but can have the original type. If they cannot respond to a message, they can delegate it to the prototype.
5. the prototype of the object can be changed at any time during running;
6. In the delegated model, changing the characteristics of the prototype will affect all objects related to the prototype;
7. In the concatenative prototype model, the prototype is the original copy cloned from other objects and further becomes the original completely independent copy. The transformation of the prototype features will not affect the cloned objects.
8. If the message cannot be responded, the caller can take additional measures (for example, change scheduling)
9. The failure of objects can be determined by their layers and classes, but by the current features.

However, we should also consider another model.

Based on Dynamic class

We believe that the difference "class VS prototype" shown in the above example is not so important in this dynamic class-based model (especially if the prototype chain is unchanged, for more accurate differentiation, it is still necessary to consider a static class ). For example, it can also use Python or Ruby (or other similar languages ). These languages use the dynamic-class paradigm. However, in some aspects, we can see some features implemented based on the prototype.

In the following example, we can see that only the prototype is based on the delegate. We can enlarge a class (prototype) to influence all objects related to this class, we can also dynamically change the class of this object at runtime (provide a new object for the delegate) and so on.

The Code is as follows:


# Python

Class A (object ):

Def _ init _ (self, ):
Self. a =

Def square (self ):
Return self. a * self.

A = A (10) # create an instance
Print (a. a) #10

A. B = 20 # provide A new attribute for the class
Print (a. B) #20-you can access

A. B = 30 # create a's own attributes
Print (a. B) #30

Del a. B # Delete attributes
Print (a. B) #20-obtain (prototype) from the class again)

# Like a prototype-based model
# You can change the object prototype at runtime.

Class B (object): # Empty class B
Pass

B = B () # B instance

B. _ class _ = A # dynamically changing A class (prototype)

B. a = 10 # create a new property
Print (B. square () #100-A class method is available at this time

# Display the references on the deletion class
Del
Del B

# But the object still has implicit references, and these methods are still available
Print (B. square () #100

# But you cannot change the class at this time.
# This is an implementation feature
B. _ class _ = dict # error

The implementation in Ruby is similar: Completely dynamic classes are also used (by the way, in the current version of Python, the comparison with Ruby and ECMAScript is to enlarge the class (prototype) (NO), we can completely change the features of objects (or classes) (adding methods/attributes to classes, and these changes will affect existing objects). However, it cannot dynamically change the class of an object.

However, this article is not specific to Python and Ruby, so we will continue to discuss ECMAScript itself.

But before that, let's take a look at some "syntactic sugar" in OOP, because many previous articles on JavaScript often address these issues.

The only wrong sentence to be noted in this section is: "JavaScript is not a class. It has an original type and can replace the class ". It is very important to know that not all class-based implementations are completely different, even if we may say "JavaScript is different", it is also necessary to consider (except the concept of "class) there are other related features.

Other features of various OOP implementations

This section briefly introduces other features and code reuse methods in various OOP implementations, including OOP implementation in ECMAScript. The reason is that the previously mentioned implementation of OOP in JavaScript has some habitual thinking limitations. The only major requirement is that it should be proved technically and ideologically. It cannot be said that JavaScript is not a pure OOP language without discovering the syntax sugar function in other OOP implementations.

Polymorphism

Objects in ECMAScript have several meanings of polymorphism.

For example, a function can be applied to different objects, just like the features of the native object (because the value is determined when the execution context is entered ):

The Code is as follows:


Function test (){
Alert ([this. a, this. B]);
}

Test. call ({a: 10, B: 20}); // 10, 20
Test. call ({a: 100, B: 200}); // 100,200

Var a = 1;
Var B = 2;

Test (); // 1, 2


However, there are also exceptions: the Date. prototype. getTime () method always has a Date object according to the standard value. Otherwise, an exception is thrown.

The Code is as follows:


Alert (Date. prototype. getTime. call (new Date (); // time
Alert (Date. prototype. getTime. call (new String (''); // TypeError

The so-called parameter polymorphism in function definition is equivalent to all data types, but only accepts the polymorphism parameter (such as the. sort sorting method of the array and Its Parameter-the multi-state sorting function ). By the way, the above example can also be considered as a parameter polymorphism.

The method in the prototype can be defined as null. All created objects should be redefined (implemented) This method (I .e., "one interface (signature), multiple implementations ").

Polymorphism is related to the Duck type we mentioned above: that is, the object type and position in the hierarchy are not so important, but if it has the necessary features, it is easy to accept (that is, the general interface is very important, and the Implementation can be varied ).

Encapsulation

There are often incorrect ideas about encapsulation. In this section, we will discuss some syntactic sugar in OOP implementation, which is also a well-known modifier: in this case, we will discuss some convenient "Sugar" implemented by OOP-well-known modifiers: private, protected, and public (or called object access level or access modifier ).

Here, I would like to remind you of the main purpose of encapsulation: encapsulation is an increase in abstraction, rather than selecting a hidden "malicious hacker" that writes something directly to your class ".

This is a big mistake: To hide and hide.

Access Level (private, protected, and public). In order to facilitate programming, it has been implemented in many object-oriented systems (which is really a very convenient syntax sugar) to describe and build systems in a more abstract way.

These can be seen in some implementations (such as Python and Ruby ). On the one hand (in Python), these _ private _ protected attributes (by the naming conventions of underlines) are not accessible from outside. On the other hand, Python can access (_ ClassName _ field_name) from outside through special rules ).

The Code is as follows:


Class A (object ):

Def _ init _ (self ):
Self. public = 10
Self. _ private = 20

Def get_private (self ):
Return self. _ private

# Outside:

A = A () # instance of

Print (a. public) # OK, 30
Print (a. get_private () # OK, 20
Print (a. _ private) # failed, because it can only be available in

# However, in Python, special rules can be used to access

Print (a. _ A _ private) # OK, 20

IN Ruby: on the one hand, it has the ability to define private and protected features. On the other hand, it also has special methods (such as instance_variable_get, instance_variable_set, and send) to obtain encapsulated data.

The Code is as follows:


Class

Def initialize
@ A = 10
End

Def public_method
Private_method (20)
End

Private

Def private_method (B)
Return @ a + B
End

End

A = A. new # new instance

A. public_method # OK, 30

A. a # failed, @ a-is a private instance variable

# "Private_method" is private and can only be accessed in Class

A. private_method # error

# However, a special metadata method name can be used to obtain data.

A. send (: private_method, 20) # OK, 30
A. instance_variable_get (: @ a) # OK, 10

The main reason is that the programmer wants to obtain the encapsulated data (note that I do not use "hidden" data in particular. If the data is incorrectly changed or has any errors in some way, it is all the responsibility of the programmer, but it is not a simple "spelling mistake" or "casually changing certain fields ". However, if this happens frequently, it is a bad programming habit and style, because the common value is to use public APIs to "talk" with objects ".

Repeat, the basic purpose of encapsulation is to abstract the data from the user of the auxiliary data, rather than to prevent hackers from hiding the data. More seriously, encapsulation does not require private modification of data to achieve software security.

Encapsulate auxiliary objects (local). We use the minimum cost, localization, and predictive changes to ask for the feasibility of public interface behavior changes. This is also the purpose of encapsulation.

In addition, the important purpose of the setter method is to abstract complex computations. For example, the setter element. innerHTML -- abstract statement -- "the HTML in this element is the following content", and the setter function in the innerHTML attribute is difficult to calculate and check. In this case, most of the problems involve abstraction, but encapsulation also occurs.

The concept of encapsulation is not only related to OOP. For example, it can be a simple function that only encapsulates various computations to make them abstract (there is no need to let users know, such as the Math function. round (......) is implemented, the user just calls it ). It is an encapsulation. Note that it is "private, protected, and public ".

In the current version of ECMAScript specification, private, protected, and public modifiers are not defined.

However, in practice, it is possible to see something named "imitating JS encapsulation ". Generally, this context is used (as a rule, constructor itself. Unfortunately, this kind of "Imitation" is often implemented, and programmers can generate pseudo-absolute non-abstract entities to set the "getter/setter method" (I will say it again, it is wrong ):

The Code is as follows:


Function (){

Var _ a; // "private"

This. getA = function _ getA (){
Return _;
};

This. setA = function _ setA (){
_ A =;
};

}

Var a = new ();

A. setA (10 );
Alert (a. _ a); // undefined, "private"
Alert (a. getA (); // 10

Therefore, everyone understands that for each created object, the getA/setA method is also created, which is also the cause of memory increase (compared with the prototype definition ). Although, in theory, objects can be optimized in the first case.

In addition, some JavaScript articles often mention the concept of "Private method". Note: The ECMA-262-3 standard does not define any concept about "Private method.

However, in some cases it can be created in the constructor, because JS is an ideological language-the object is completely mutable and has unique features (under certain conditions in the constructor, some objects can obtain additional methods, but others cannot ).

In addition, in JavaScript, if the encapsulation is misinterpreted as an understanding that prevents malicious hackers from automatically writing certain values in place of the setter method, the so-called "hidden) "and" private "are not quite" hidden ". Some implementations can call the context to the eval function (which can be tested on SpiderMonkey1.7) obtain the value on the relevant scope chain (and all corresponding variable objects ).

The Code is as follows:


Eval ('_ a = 100', a. getA); // or a. setA, because the [[Scope] of the "_ a" Two Methods
A. getA (); // 100

Alternatively, you can directly access the activity object (such as Rhino) in the Implementation. You can change the value of the internal variable by accessing the corresponding properties of the object:

The Code is as follows:


// Rhino
Var foo = (function (){
Var x = 10; // "private"
Return function (){
Print (x );
};
})();
Foo (); // 10
Foo. _ parent _. x = 20;
Foo (); // 20


Sometimes, in JavaScript, the data "private" and "protected" is achieved by prefixing the variable with an underscore (but this is only a naming convention compared with Python ):

Var _ myPrivateData = 'teststring ';
It is often used to enclose the execution context in parentheses, but for real auxiliary data, it is not directly associated with the object, but it is convenient to abstract it from external APIs:

The Code is as follows:


(Function (){

// Initialize the context

})();

Multi-Inheritance

Multi-inheritance is a convenient syntactic sugar for code reuse and improvement (if we can inherit a class at a time, why cannot we inherit 10 classes at a time ?). However, due to the shortcomings of Multi-inheritance, implementation is not popular.

ECMAScript does not support multi-inheritance (that is, there is only one object that can be used as a direct prototype), although its ancestor's self-programming language has such capabilities. However, in some implementations (such as SpiderMonkey), _ noSuchMethod _ can be used to manage scheduling and delegation to replace the prototype chain.

Mixins

Mixins is a convenient way to reuse code. Mixins has been recommended as a substitute for multi-inheritance. These independent elements can be mixed with any object to expand their functions (So objects can also be mixed with multiple Mixins ). The ECMA-262-3 specification does not define the concept of "Mixins", but according to the Mixins definition and ECMAScript has a dynamic variable object, there is no obstacle to using Mixins to simply expand features.

Typical Example:

The Code is as follows:


// Helper for augmentation
Object. extend = function (destination, source ){
For (property in source) if (source. hasOwnProperty (property )){
Destination [property] = source [property];
}
Return destination;
};

Var X = {a: 10, B: 20 };
Var Y = {c: 30, d: 40 };

Object. extend (X, Y); // mix Y into X
Alert ([X. a, X. B, X. c, X. d]); 10, 20, 30, 40

Please note that I take these definitions ("mixin", "mix") mentioned in the quotes in the ECMA-262-3, and there is no such concept in the Specification, in addition, it is not a mix but a common method to expand objects through new features. (IN Ruby, the concept of mixins is officially defined. mixin creates a reference containing a module to replace all attributes of this module with simple copying to another module. In fact, the following is true: create an additional object (prototype) for the delegate )).

Traits

Traits and mixins have similar concepts, but they have many functions (according to the definition, because mixins can be applied, they cannot contain States because they may cause naming conflicts ). According to ECMAScript, Traits and mixins follow the same principles. Therefore, this specification does not define the concept of "Traits.

Interface

The interfaces implemented in some OOP are similar to mixins and traits. However, compared with mixins and traits, the interface must implement the method signature of the class.

An interface can be considered as an abstract class. However, compared with the abstract class (the methods in the abstract class can only implement one part, and the other part is still defined as a signature), inheritance can only be a single inheritance of the base class, but can inherit multiple interfaces, for this reason, you can use interfaces (multiple mixing) as an alternative to multi-inheritance.

ECMA-262-3 standards neither define the concept of "interface" nor define the concept of "abstract class. However, as an imitation, it can be implemented by an "empty" method (or an exception thrown in an empty method, telling developers that this method needs to be implemented.

Object combination

Object combination is also one of dynamic code reuse technologies. Unlike the inheritance with high flexibility, object combinations implement a dynamic and variable delegate. This is also the basis of the delegated prototype. In addition to the dynamic mutable prototype, this object can be a delegated aggregation object (create a combination as the result -- aggregation), send messages to the object, and delegate to the delegate. This can be more than two delegates, because its dynamic characteristics determine that it can be changed at runtime.

The example of _ noSuchMethod _ already mentioned is as follows, but it also shows how to explicitly use the delegate:

For example:

The Code is as follows:


Var _ delegate = {
Foo: function (){
Alert ('_ delegate. foo ');
}
};

Var agregate = {

Delegate: _ delegate,

Foo: function (){
Return this. delegate. foo. call (this );
}

};

Agregate. foo (); // delegate. foo

Agregate. delegate = {
Foo: function (){
Alert ('foo from new delegate ');
}
};

Agregate. foo (); // foo from new delegate

This object relationship is called "has-a", while integration is the "is-a" relationship.

Due to the lack of display combinations (flexibility compared with inheritance), it is also possible to add intermediate code.

AOP features

Function decorators can be used as an aspect-oriented function. ECMA-262-3 specifications do not clearly define the concept of "function decorators" (relative to Python, which is officially defined in Python ). However, functions with function-based parameters can be decorated and activated in some aspects (by applying the so-called recommendations ):

Example of the simplest decorator:

The Code is as follows:


Function checkDecorator (originalFunction ){
Return function (){
If (fooBar! = 'Test '){
Alert ('wrong parameter ');
Return false;
}
Return originalFunction ();
};
}

Function test (){
Alert ('test function ');
}

Var testWithCheck = checkDecorator (test );
Var fooBar = false;

Test (); // 'test function'
TestWithCheck (); // 'wrong parameter'

FooBar = 'test ';
Test (); // 'test function'
TestWithCheck (); // 'test function'

Conclusion

In this article, we have clarified the introduction to OOP (I hope these materials will be useful to you). In the next chapter, we will continue to implement ECMAScript in object-oriented programming.

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.