[Colleagues' original articles] JavaScript Object-Oriented Programming

Source: Internet
Author: User
Tags hasownproperty
Document directory
  • Javascript object-oriented programming, Part 1: Inheritance

Javascript object-oriented programming, Part 1: Inheritance

Author: lzlhero <lzlhero_at_eyou.com>
Release: heiyeluren Time: 2005-08-25

We will show you how JavaScript implements the following in object-oriented languages:InheritanceAt the same time, these examples will show you how to implement class encapsulation. Here, we will not discuss polymorphism implementation.

Although Javascript is a scripting language, it also supports very powerful object-oriented programming. although it does not have classes and instances, it has objects, prototypes, and implicit inheritance. we will explain how to simulate inheritance and the relationship between its superclass and subclasses. prototype is the key to understanding the concept of inheritance. We will teach you how to build a prototype and how to detect whether an object is another prototype, differences between the Javascript model and Java object-oriented programming. we will also show you how to detect various attributes of an object. in another article, I will explain in detail"Prototype chain)"Knowledge.

This article provides a lot of referencesWebreference.comMedium"Object-oriented programming with JavaScript, Part I: Inheritance"Content, many content I have carried out a detailed test and further discussion, to ensure that the content will not make too many mistakes.
Address: http://www.webreference.com/js/column79/

Features of object-oriented language

Object-oriented design is based on three main principles: encapsulation, inheritance, and polymorphism. A programming language supports Oo (Object-Oriented) design. This can be said only when its syntax supports the above three concepts. this language should provide you with some methods so that you can easily define and use these examples. encapsulation involves the concept of turning an object into a "black box. when you use an object, you don't have to know how it works internally or how it works. this object only needs to provide the absolutely useful information in the interface mode. this object should provide friendly interfaces for you to use its limited property sets and method sets. encapsulation also means that an object contains everything it needs, including data and operations on it. the concept of encapsulation is very powerful because it allows a large software project to be effectively assigned to every developer. For everyone in the team, they only need to focus on the objects they implement, instead of focusing too much on others' implementations. the overhead of the development project increases the number of members and interfaces in the development team exponentially. encapsulation is the most popular OO design concept since the "software crisis.

Software reuse is another important feature of OO design ideas. the main method to realize this idea in the software system is inheritance. class is the function of defining objects. A superclass is a new class, or a source class created by a subclass. A subclass inherits the methods and attributes from its superclass. in fact, all subclasses are automatically generated, saving a lot of work. you do not need to define these subclasses one by one. of course, you can reload the inherited methods and attributes. in fact, no one has pointed out which subclass should be created exactly like its superclass unless you have not overloaded any attributes and methods.

Polymorphism may be the most complex of the three concepts. essentially, each object can process different data types. you do not have to create different classes to process different data types. A typical example is the drawing class. You do not have to write different classes to achieve circle, rectangle, and ellipse. you can create a smart class to call specific methods to operate on specific shapes.

Implement inheritance through Functions

Although JavaScript does not support displaying inheritance operators, You can implement implicit inheritance in actual ways. there are two common methods for implementing class inheritance. the first method to define a class as a subclass is to call a superclass constructor within the class that defines the subclass function. see the following example:

// Superclass Constructor
Function superclass (){
This. Bye = superbye;
This. Hello = superhello;
}

// Subclass Constructor
Function subclass (){
This. inheritfrom = superclass;
This. inheritfrom ();
This. Bye = subbye;
}

Function superhello (){
Return "hello from superclass ";
}

Function superbye (){
Return "Bye from superclass ";
}

Function subbye (){
Return "Bye from subclass ";
}

// Test the functions of the constructor.
Function printsub (){
VaR newclass = new subclass ();
Alert (newclass. Bye ());
Alert (newclass. Hello ());
}

When you run the printsub function above, it will execute subbuy and superhello functions in sequence. we can see that the bye and hello methods are first defined in superclass. however, in subclass, the bye method is also overloaded. The function of the first two rows of subclass constructor only implements a simple original inheritance operation, however, it is an inheritance operation completed by executing the inheritfrom method. the inheritance process first assigns the object prototype of superclass to the inheritfrom method under subclass, and then after the superclass constructor is executed, the attributes of superclass are automatically added to the subclass attribute list. this is mainly caused by the inheritfrom (superclass) constructor called through this in subclass. When superclass constructor is called in this way, the javascript interpreter will understand this in superclass and this in subclass as the this keyword in the same scope, so it produces the inheritance effect.

In addition, it should be noted that for any instantiated object, you add attributes or methods to it as needed, as shown below:

VaR newclass = new subclass ();
Newclass. addprop = "added property to instance object ";

Obviously, the attributes and methods added in this way are only valid for the currently instantiated object and will not affect all instances of the same type of objects. Undoubtedly, it is a unique object instance you have created.

Implement inheritance through prototype

The second and more powerful method is to create a super-Class Object and assign it to the prototype attribute of the subclass object to create inheritance of the subclass. assume that our superclass is superclass and the subclass is subclass. the prototype assignment format is as follows:

Subclass. Prototype = new superclass;

For the implementation method of prototype inheritance, let's rewrite the previous code, for example:

// Superclass Constructor
Function superclass (){
This. Bye = superbye;
This. Hello = superhello;
}

// Subclass Constructor
Function subclass (){
This. Bye = subbye;
}
Subclass. Prototype = new superclass;

Function superhello (){
Return "hello from superclass ";
}

Function superbye (){
Return "Bye from superclass ";
}

Function subbye (){
Return "Bye from subclass ";
}

// Test the functions of the constructor.
Function printsub (){
VaR newclass = new subclass ();
Alert (newclass. Bye ());
Alert (newclass. Hello ());
}

We can see that, except for changing the content of the first two lines in subclass in the first Inheritance Method to the prototype assignment statement outside the function, there is no other change, however, the Code Execution effect is the same as the previous one.

Add attributes for created objects

Inheritance implemented by prototype is better than inheritance implemented by functions because it supports dynamic inheritance. after the constructor is complete, you can use the prototype attribute to define other methods and attributes of the superclass, And the subclass object under it will automatically obtain new methods and attributes. the following is an example. You can see its effect.

Function superclass (){
This. Bye = superbye;
This. Hello = superhello;
}

Function subclass (){
This. Bye = subbye;
}
Subclass. Prototype = new superclass;

Function superhello (){
Return "hello from superclass ";
}

Function superbye (){
Return "Bye from superclass ";
}

Function subbye (){
Return "Bye from subclass ";
}

VaR newclass = new subclass ();

/*****************************/
// Add the blessyou attribute dynamically
Superclass. Prototype. blessyou = superblessyou;

Function superblessyou (){
Return "Bless you from superclass ";
}
/*****************************/

Function printsub (){
Alert (newclass. Bye ());
Alert (newclass. Hello ());
Alert (newclass. blessyou ());
}

This is what we often see as a technique for adding other attributes and methods to internal objects, such as string and math. you can also use prototype to reload the attributes and methods of any internal and custom objects. when calling and executing, it will call the methods and attributes you have defined. the following is an example:

// Add method for internal string object
String. Prototype. mymethod = function (){
Return "My define method ";
}

// Overload method for the internal string object
String. Prototype. tostring = function (){
Return "My define tostring method ";
}

VaR myobj = new string ("foo ");

Alert (myobj. mymethod ());
Alert (myobj );
Alert ("foo". tostring ());

Note that all prototype attributes in JavaScript are read-only. you can add or reload properties and methods for the internal object prototype as above, but you cannot change the prototype of the internal object. however, a custom object can be assigned to a new prototype. that is to say, this is meaningless.

Function employee (){
This. Dept = "HR ";
This. Manager = "John Johnson ";
}

String. Prototype = new employee;

VaR mystring = new string ("foo ");

The above program will not report an error after running, but obviously, if you call mystring. Dept, you will get an undefined value.

In addition, an isprototypeof () method under prototype is often used to determine whether the specified object exists in the prototype chain of another object. The syntax is as follows:

Object1.prototype. isprototypeof (0bject2 );

The preceding format is used to determine whether object2 has an object1 prototype chain. The example is as follows:

Function person (){
This. Name = "Rob Roberts ";
This. Age = 31;
}

Function employee (){
This. Dept = "HR ";
This. Manager = "John Johnson ";
}

Employee. Prototype = new person ();

VaR Ken = new employee ();

If you execute employee. Prototype. isprototypeof (KEN), person. Prototype. isprototypeof (KEN), and object. Prototype. isprototypeof (KEN), true is returned.

Used for specific inheritance detection in Netscape

In Netscape Browser 4.x to 6 and Mozilla series browsing, JavaScript stores prototype relationships between objects in a special internal property object, _ PROTO _ (the front and back are two underlines ). the following is an example:

Function shape (){
This. borderwidth = 5;
}

Function Square (){
This. Edge = 12;
}

Square. Prototype = new shape;

Mypicture = new square;

Alert (mypicture. _ PROTO __);
Alert (mypicture. borderwidth );

Because the script has run square. prototype = new shape statement, so mypicture has an internal attribute _ PROTO _ pointing to the shape object __. during script execution, when you want to obtain a property value of an object and the object is an object created by assigning values through the prototype, when you do not define a property, the javascript parser will view its _ PROTO _ property object, that is, its prototype object, and then enumerate all attributes in its prototype. The result is either that this property exists, this attribute is not available. if this property is not available, enumerate the prototype objects under the prototype object until the process ends. we don't know all the operations in these Javascript Engines. The following content explains this problem.

In fact, for all custom objects, whether or not prototype assignment is used, it has a _ PROTO _ internal object. if an object is inherited by multiple layers of prototype, all the inherited attributes can be traversed through a simple layer loop without any recursive algorithm, this is because the JavaScript engine has automatically done this for us. example:

Function shape (){
This. borderwidth = 5;
}

Function Square (){
This. Edge = 12;
}

Function roundsquare ()
{
This. Radio = 0.5;
}

Square. Prototype = new shape;
Roundsquare. Prototype = new square;

VaR mypicture = new roundsquare;

For (property in mypicture. _ PROTO __){
Alert (property );
}

We can also change the following loop to traverse all attributes inherited by a subclass object, as shown below:

For (property in roundsquare. Prototype ){
Alert (property );
}

If you are not afraid of trouble, we can even retrieve the original attribute values defined in the constructor Through cascade.

Alert (mypicture. _ PROTO _. _ PROTO _. borderwidth );

Whether or not you have modified this attribute value, the attribute value obtained through the preceding statement is the original defined value. let's move on to this idea. The following Code involves another problem, which is related to prototype chain. the Code is as follows:

Function State (){
}

Function City (){
}
City. Prototype = new State;

Function Street (){
}

Street. Prototype = new city;

VaR universityavenue = New Street ();

Function tryit (){
Alert (universityavenue. _ PROTO __= = Street. Prototype );
Alert (universityavenue. _ PROTO _. _ PROTO __= =
City. Prototype );
Alert (universityavenue. _ PROTO __
= State. Prototype );
Alert (universityavenue. _ PROTO __.
_ PROTO __= = object. Prototype );
Alert (universityavenue. _ PROTO __.
_ PROTO _. _ PROTO __= = NULL );
}

When you execute the tryit function, all displays are true. that is, prototype of the subclass object. _ PROTO _ always equals to the prototype attribute of the superclass object; the prototype of the superclass object. _ PROTO _ always equals to object. prototype; object. prototype. _ PROTO _ is always null, And the _ PROTO _ of the Instance Object is always equal to the prototype of its class object, this is why any custom object has the _ PROTO _ attribute. for the above description, the corresponding code is as follows:

Street. Prototype. _ PROTO _ = city. Prototype // true
State. Prototype. _ PROTO _ = object. Prototype // true
Object. Prototype. _ PROTO _ = NULL // true
Universityavenue. _ PROTO _ = Street. Prototype // true

Simulate and implement the instanceof Function

Based on the content in the previous section, we learned about the _ PROTO _ features supported by Netscape. in this section, we will use this feature to create our own instance object detection function.

In many cases, we need to determine whether an object is defined by a class. In other languages, you can use the instanceof function to determine whether an object is defined. javascript also provides an instanceof operator. On the basis of _ PROTO _, we can define the same function by ourselves, although it seems to be repetitive, but it helps us to have a deeper understanding of _ PROTO. the following code is only used to describe functions. In actual applications, you do not need to repeatedly define the instanceof function, just use the instanceof operator.

Function instanceof (object, constructorfunction ){
While (object! = NULL ){
If (Object = constructorfunction. Prototype)
{Return true}
Object = object. _ PROTO __;
}
Return false;
}
Function State (){
}

Function City (){
}
City. Prototype = new State;

Function Street (){
}

Street. Prototype = new city;

VaR universityavenue = New Street ();
Function demo (){
Alert ("instanceof (universityavenue, street) is" +
Instanceof (universityavenue, street ));
Alert ("instanceof (universityavenue, city) is" +
Instanceof (universityavenue, city ));
Alert ("instanceof (universityavenue, State) is" +
Instanceof (universityavenue, State ));
}

You will see that all running results are true, and its principle is the same as the level-one judgment in the previous section. it turns out that the running result is consistent with that of the instanceof operator.

You can use the constructor attribute to detect the superclass of any object. This attribute returns the constructor called when a new object is created using the new operator. The returned value is the function object type. because internal objects support the constructor attribute, and some objects (including internal objects and custom objects) are inherited from objects, all objects support this attribute. let's look at the example below in detail:

Function employee (){
This. Dept = "HR ";
This. Manager = "John Johnson ";
}

Function printprop (){
VaR Ken = new employee ();
Alert (Ken. constructor );
}

After calling the printprop function, you will see the definition Text of the employee function displayed in the pop-up box, in fact, Ken. the return value of constructor is itself a function object type, and the tostring method is implicitly called in alert. for the class object itself, you can also call prototype. constructor to retrieve its constructor.

Classification and printing of Objects

Javascript supports three main types of objects: internal objects, host objects, custom objects, and special external objects, such as ActiveX objects or XPCOM objects. internal objects are supported by the Javascript language, such as objects, math, and number objects. all internal objects start with uppercase letters and are case-sensitive. if you want to use a mathematical constant Pi, you must write it as math. pi. If you write it as math. pi, JavaScript will display an error. the Host object is supported by the browser to interact with the viewed document, such as document, window, and frames. the Host Object features that all objects start with lowercase letters. javascript itself is case sensitive, so you cannot mix the case. the rest is just a custom object. You can define your object in lower case or lower case, but it must comply with the basic naming rules. as shown below, this is a custom object:

Function employee (){
This. Dept = "HR ";
This. Manager = "John Johnson ";
}

Function printprop (){
VaR Ken = new employee ();
For (property in Ken ){
Alert (property );
}
}

As mentioned above, all internal and custom objects are inherited from object objects, which are superclass objects of all objects. you can create an object instance. as follows:

VaR myobject = new object ();

Objects of the object type have many attributes and Methods. You can view related manuals. the above just defines the simplest empty object. You can also input parameters for the object constructor, which will return the instantiated object of the corresponding type value. remember, the type of the returned value is of an object type (such as string, number, or object ). this method is different from directly assigning values to strings or numerical constants, which mainly indicates the type. as follows:

VaR myobject = new object ("foo"); // the return value type is object.
VaR myobject = new string ("foo"); // the return value type is object.
And
VaR myobject = "foo"; // the return value type is string.

You can see this subtle difference in the type column of the debugger, which is the difference between the simple type and the object type. however, you can see no internal differences through the alert call, because during the calling of alert, all object type values will be automatically called to convert the tostring type, the conversion rules are described in the Javascript manual. if alert is a custom object and does not define the tostring method, the returned value is "[object]". for a math object, when you view its math. for the constructor attribute, you will get a function object ()... "object constructor, which returns" function () with other objects ()... the constructor is very different. the reason is simple, because the math object cannot be created through the new operator.

In addition, if the value in the input object constructor is an object, it will return the object intact. Remember, this operation is just a reference, not a copy.

Attributes of the request object

In the previous sample code, an example of listing object properties cyclically has been displayed. in fact, through... the in statement can traverse any object or array, its elements, attributes, and methods. example:

Function employee (){
This. Dept = "HR ";
This. Manager = "John Johnson ";
}

Function printprop (){
VaR Ken = new employee ();
For (property in Ken ){
Alert (property + ":" + Ken [property]);
}
}

During the traversal test, you will find that attributes under custom objects and host objects can be cited. For internal objects, almost no attributes can be traversed, why almost? Because the JavaScript engine of Mozilla kernel browsing is different from that of IE kernel browsers, some content can be cited in Mozilla, but the principle of enumeration is unknown.

For each object, you can also use the hasownproperty method to check whether it has a certain attribute or method. hasownproperty is the method of the object, so all objects have this method. however, you must note that this method can only detect members defined by the keyword this. If a member is defined by the prototype chain, this method returns false. that is to say, attributes and methods inherited by prototype and their attributes and methods defined by prototype cannot be detected through hasownproperty. from this, we can see that the attributes and methods defined by the this keyword are in the same address space as the object itself, and the properties and methods defined by prototype are as follows, it is managed through the so-called "prototype chain", and its attributes and methods are not in the same address space. When it calls this property or method, you must use a linked list to index a property or method under it. that is to say, calling properties and methods defined in prototype will have a "backtracking" operation similar to a linked list.

Similar to hasownproperty, for each attribute in an object, we can also use propertyisenumerable to test whether it can be enumerated as follows:

Function employee1 (){
This. Dept = "HR ";
This. Manager = "John Johnson ";
This. month = new array ("Jan", "FEB", "Mar ");
}

VaR Ken = new employee1 ();

Ken. Month. propertyisenumerable (0 );

We can see that the syntax is propertyisenumerable followed by the element index of the array or the attribute name in the object. Similarly, it is not considered for the attribute or method in the prototype chain. Of course, false is returned for the result.

Comparison between JavaScript and Java

Unlike Java, a class-based language, JavaScript is a prototype-based language. this feature affects every aspect. for example, the term "instance" has a special meaning in a class-based language. It indicates that an instance is an independent entity belonging to a special class and is a real implementation of the class definition. In JavaScript, the term instance does not mean this, because in its syntax, classes and instances are no different. the instance can be used to indicate that an object is generated using a special constructor. as follows:

Function superclass (){
This. Bye = superbye;
This. Hello = superhello;
}

Function subclass (){
This. Bye = subbye;
}
Subclass. Prototype = new superclass;

Function superhello (){
Return "hello from superclass ";
}

Function superbye (){
Return "Bye from superclass ";
}

Function subbye (){
Return "Bye from subclass ";
}

VaR newclass = new subclass ();

Newclass is an example of subclass, which is generated through the subclass constructor. If you use a class-based language, the following shows the equivalent Implementation of Java.

Public class superclass {
Public superclass (){
This. Bye = superbye;
This. Hello = superhello;
}
}
Public class subclass extends superclass {
Public subclass (){
This. Bye = subbye;
}
}

Conclusion

In the above sections, we will explain in detail the object-oriented implementation in javascipt, or it can only be said to be a simulated implementation. during this period, we will show you the implementation methods. this article also describes how to detect the relationship between objects, how to print attributes and test a specific attribute, and a simple comparison between JavaScript and Java. however, this is obviously not enough. Therefore, JavaScript object-oriented programming is very diverse and the format is also very complicated. I plan to summarize the Encapsulation Format questions in the following content, focusing on the content and implementation related to object methods, and the prototype chain mentioned above) problem.

Declaration: Reprinted please indicate from http://blog.csdn.net/heiyeshuwu

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.