JavaScript Object-oriented programming (bottom)--Inheritance and polymorphism "go"

Source: Internet
Author: User
Tags variable scope

JavaScript Object-oriented programming (bottom)--Inheritance and polymorphism

Earlier we discussed how to implement encapsulation of private instance members, public instance members, private static members, public static members, and static classes in the JavaScript language. This time, let's talk about the other two elements in object-oriented programming: inheritance and polymorphism. 1 is also a few basic concepts

Why do you say it again?

In discussing inheritance, we have outlined some basic concepts that are closely related to encapsulation, and the basic concepts that we are going to discuss today are primarily related to inheritance and polymorphism, but they are also associated with encapsulation. 1.1 Defining and assigning values

Variable definition refers to the use of

var A;

This form to declare the variable.

function definition refers to the use of

Function A (...) {...}

This form to declare the function.

var a = 1;

is a two process. The first procedure is to define variable A, and the second procedure is to assign a value to variable a.

Same

var a = function (...) {};

is also two procedures, the first procedure is to define variable A and an anonymous function, the second procedure is to assign the anonymous function to the variable A.

variable definitions and function definitions are done before the entire script executes, and variable assignments are done at the execution stage.

The function of a variable definition is simply to indicate its scope to the declared variable, the variable definition does not give the variable an initial value, any variable that is not defined but is directly used, or a variable that is defined but not assigned, their value is undefined.

The function definition also defines the function body structure in addition to declaring the function's extraterritorial scope. This process is recursive, that is, the definition of the function body includes the definition of variables and functions in the body of the function.

We can understand this more clearly by following this example:

alert (a);
alert (b);
alert (c);
var a = "a";
function A () {}
Function B () {}
var B = "B";
var c = "C";
var c = function () {}
alert (a);
alert (b);
alert (c);

Guess what the results of this program do? Then execute it and see if it's what you think, and if it's the same as you think, it means you understand what it says.

The result of this procedure is very interesting, although the first alert (a) is at the top, but you will find that it outputs a value of function A () {}, which means that the function definition is actually completed before the entire program executes.

Again, B, the function B is defined before the variable B, but the first alert (b) output is still function B () {}, which means that the variable definition does not do anything to the variable, it simply declares its scope, and it does not overwrite the function definition.

Finally, C, the first alert (c) output is undefined, which shows that var c = function () {} is not defined for function C, it simply defines a variable c and an anonymous function.

Look at the second alert (a) and you'll see that the output is a, which means that the assignment statement is actually done during execution, so it overrides the definition of function A.

The second alert (b) is also, of course, the output is B, which means that a variable assignment with the same name as a function will always overwrite the function definition regardless of whether the assignment statement is written before or after the function definition.

The second alert (c) outputs the function () {}, which means that the assignment statement is executed sequentially, and subsequent assignments override the previous assignment, regardless of whether the assigned value is a function or another object.

Understanding the above, I think you should know when to use function x (..) {...}, when to use var x = function (...) {...} , huh?

Finally, it is important to note thatif variable definitions and function definitions are present in eval, they are completed in the execution phase. So, don't use eval! to be a last resort. In addition, even if you want to use eval, do not use local variables and local methods inside! 1.2 This and execution context

We have been exposed to this in the previous discussion of encapsulation. In the discussion of encapsulation, we see that this is the instantiated object itself that represents the class where this is located. Is that really the case?

Let's take a look at the following example:

var x = "I ' m a global variable!";
Function method () {
alert (x);
alert (this.x);
}
function Class1 () {
Private field
var x = "I ' m a private variable!";
Private method
function Method1 () {
alert (x);
alert (this.x);
}
var method2 = method;
public field
this.x = "I ' m a object variable!";
Public method
This.method1 = function () {
alert (x);
alert (this.x);
}
This.method2 = method;
Constructor
{
This.method1 (); I ' m a private variable!
I ' m A object variable!
THIS.METHOD2 (); I ' m a global variable!
I ' m A object variable!
Method1 (); I ' m a private variable!
I ' m a global variable!
Method2 (); I ' m a global variable!
I ' m a global variable!
Method1.call (this); I ' m a private variable!
I ' m A object variable!
Method2.call (this); I ' m a global variable!
I ' m A object variable!
}
}

var o = new Class1 ();
Method (); I ' m a global variable!
I ' m a global variable!
O.method1 (); I ' m a private variable!
I ' m A object variable!
O.METHOD2 (); I ' m a global variable!
I ' m A object variable!

Why is this the result?

Let's take a look at what the execution context is. What is the execution context?

If you are currently executing a method, the execution context is the object that the method is attached to, and if you are currently executing a procedure that creates an object (that is, created through new), the object being created is the execution context.

If a method is not explicitly attached to an object at execution time, its execution context is a global object (top-level object), but it is not necessarily subordinate to the global object. Global objects are determined by the current environment. In a browser environment, the global object is the Window object.

Global variables and global functions that are defined outside of all functions are attached to global objects, and local variables and local functions defined within functions are not attached to any object.

Does the execution context have anything to do with a variable scope?

The execution context is different from the scope of the variable.

when a function assigns a value to another variable, the scope of the variable used within the function does not change, but its execution context becomes the object to which the variable is attached (if the variable has a subordinate object).

the call and apply methods on a Function prototype can alter the execution context, but also do not change the scope of the variable.

To understand these words, you just need to remember a little bit:

The scope of a variable is determined at the time of definition, it never changes, and the execution context is determined at execution time, and it can be changed at any time.

It is not difficult for us to understand the above example. THIS.METHOD1 () This statement (note that this is not yet in the body of the function) is being created, and the current execution context is the object being created, so this is also the object currently being created, in This.method1 () When this method executes (this refers to entering the function body), the object being attached to the executing method is the object that is being created, so the this.x is the same object, so the output you see is I ' m a object variable! The

While executing the METHOD1 () function (which refers to entering the function body), method1 () is not explicitly attached to an object, although it is defined in Class1, but is not attached to the Class1, nor is it attached to the object after the Class1 instantiation, Only its scope is limited to the Class1. Therefore, its subordinate object is actually a global object, so when it executes to alert (this.x), this.x becomes the x that we defined in the global environment as "I m a global variable!".

METHOD2 () is defined in Class1, but method () is defined outside of Class1, and when method is assigned to METHOD2, it does not change the scope of the method, so when METHOD2 is executed, it is still in Metho D is executed within the defined scope, so what you see is two I ' m a global variable! The output. Similarly, when THIS.METHOD2 () is called, alert (x) outputs I ' m a global variable! That's the reason.

Because call alters the execution context, This.x becomes the I ' m a object variable! through Method1.call (this) and Method2.call (this). However, it cannot change the scope, so X is still the same as the result when the call method is not used.

When we execute O.METHOD1 () behind us, alert (x) does not use this to indicate the execution context of x, then x represents the most recently defined variable in the scope of the currently executing function, so the output is I ' m a private variable!. Final output I ' m a object variable! I don't think I can tell you why, you know? :D 2 inheritance and polymorphism 2.1 starting from encapsulation

As we said earlier, the purpose of encapsulation is to achieve data hiding.

But in a deeper layer, encapsulation in JavaScript has several benefits:

1, stealth implementation details, when the private part of the implementation of the full rewrite, do not need to change the behavior of the caller. This is another object-oriented language to achieve the main purpose of encapsulation.

2. In JavaScript, local variables and local functions are accessed faster, so private fields are encapsulated in local variables, and private methods are encapsulated in a local way to improve the execution efficiency of the scripts.

3, for JavaScript compression obfuscation (as far as I know, the best JavaScript analysis, compression, obfuscation is JSA), local variables and local function names can be replaced, and global variables and global function names can not be replaced (in fact, for The JavaScript Script parser works the same way). Therefore, whether for open source or non-open source JavaScript programs, when the private fields and private methods use encapsulation technology, write code can give them long enough to define the ideographic name, increase the readability of the Code, and when published, they can be replaced by some very short name (usually a single character name), This allows for full compression and confusion. and reduce the bandwidth consumption, but also can really realize the hidden details.

So, encapsulation is very useful for JavaScript!

So what is the implementation of inheritance in JavaScript? 2.2 Why to inherit

In other object-oriented programming languages, inheritance, in addition to reducing the writing of repetitive code, is most useful in order to achieve polymorphism. This is especially true in strongly typed languages:

1. In a strongly typed language, a variable cannot be given two values of a different type, unless the two types are compatible with the type of the variable, and this compatible relationship is implemented by inheritance.

2. In a strongly typed language, the extension and rewriting of a method cannot be done directly to an existing type, and the only way to extend a type is to inherit it and expand and rewrite it in its subclasses.

Therefore, for strongly typed object-oriented languages, the implementation of polymorphism depends on the implementation of inheritance.

For the JavaScript language, inheritance is less important for polymorphic implementations:

1. In the JavaScript language, a variable can be given any type of value, and the same name method on any type of object can be called in the same way.

2, in the JavaScript language, the existing types can be directly through the prototype method of expansion and rewriting.

So, in JavaScript, the main function of inheritance is to reduce the writing of repetitive code.

The next two ways of implementing inheritance may be familiar to us, one is the prototype inheritance method, the other is the call inheritance method, neither of which has side effects. We are mainly talking about the nature of the two approaches and where they need to be noted. 2.3 Prototype Inheritance Law

In JavaScript, each class (function) has a prototype that is passed to the instantiated object of the class when the class is instantiated. There is no prototype on the instantiated object, but it can be used as a prototype of another class (function) that, when instantiated with a class that is a prototype of the object, is passed on to the instantiated object of the class to which it is prototyped. This is the essence of prototype inheritance.

Prototype inheritance is also an inherited method used by many native objects in JavaScript.

function ParentClass () {
Private field
var x = "I ' m a parentclass field!";
Private method
function Method1 () {
alert (x);
Alert ("I ' m a ParentClass method!");
}
public field
this.x = "I ' m a ParentClass object field!";
Public method
This.method1 = function () {
alert (x);
alert (this.x);
Method1 ();
}
}
ParentClass.prototype.method = function () {
Alert ("I ' m a ParentClass prototype method!");
}
Parentclass.staticmethod = function () {
Alert ("I ' m a parentclass static method!");
}

function Subclass () {
Private field
var x = "I ' m a subclass field!";
Private method
function Method2 () {
alert (x);
Alert ("I ' m a subclass method!");
}
public field
this.x = "I ' m a subclass object field!";
Public method
THIS.METHOD2 = function () {
alert (x);
alert (this.x);
Method2 ();
}
This.method3 = function () {
Method1 ();
}
}

Inherit
Subclass.prototype = new ParentClass ();
SubClass.prototype.constructor = subclass;

Test
var o = new Subclass ();

Alert (o instanceof parentclass); True
Alert (o instanceof Subclass); True

alert (o.constructor); function Subclass () {...}

O.method1 (); I ' m a parentclass field!
I ' m a subclass object field!
I ' m a parentclass field!
I ' m a parentclass method!
O.METHOD2 (); I ' m a subclass field!
I ' m a subclass object field!
I ' m a subclass field!
I ' m a subclass method!
O.method (); I ' m a parentclass prototype method!

O.method3 (); Error!!!
Subclass.staticmethod (); Error!!!

The above example is a good illustration of how inheritance is implemented using the prototype inheritance method.

The key to using the prototype inheritance is a two-step operation:

you first create an instantiated object of the parent class, and then assign the object to the prototype property of the subclass.

This allows all public instance members in the parent class to inherit from the quilt class. And when judged by the instanceof operator, the instantiated object of the subclass belongs to both the subclass and the parent class.

The subclass itself is then assigned a value to its prototype constructor property. (Note: There is no () when assigning a value here! )

This step is to ensure that when you view the constructor property of the instantiated object of a subclass, you see the definition of the subclass, not the definition of its parent class.

Next, with the result of the call to O.method1 (), we see that in the public instance method inherited by the subclass, if the private instance field or private instance method is called, then the private instance members that are called belong to the parent class.

Similarly, with the result of a call to O.METHOD2 () we see that the instance method defined in the subclass, if a private instance field or private instance method is called, is a subclass of those private instance members that are called.

By the result of the call to O.method () we see that the method defined on the parent class prototype inherits from the Quilt class.

By the result of the call to O.METHOD3 () we see that the instance method defined in the subclass cannot access the private instance members defined in the parent class.

Finally, with the result of the call to Subclass.staticmethod () we see that static members are not inherited. 2.4 Calling the inheritance method

The essence of invocation inheritance is that in the constructor of the subclass, the constructor method of the parent class is executed on the execution context of the subclass, and all of the content of the parent class constructor method that is manipulated by this way is actually the content on the instantiated object of the child class of the operation. Therefore, this is done only to reduce duplication of code writing.

function ParentClass () {
Private field
var x = "I ' m a parentclass field!";
Private method
function Method1 () {
alert (x);
Alert ("I ' m a ParentClass method!");
}
public field
this.x = "I ' m a ParentClass object field!";
Public method
This.method1 = function () {
alert (x);
alert (this.x);
Method1 ();
}
}
ParentClass.prototype.method = function () {
Alert ("I ' m a ParentClass prototype method!");
}

Parentclass.staticmethod = function () {
Alert ("I ' m a parentclass static method!");
}

function Subclass () {
Inherit
Parentclass.call (this);

Private field
var x = "I ' m a subclass field!";
Private method
function Method2 () {
alert (x);
Alert ("I ' m a subclass method!");
}
public field
this.x = "I ' m a subclass object field!";
Public method
THIS.METHOD2 = function () {
alert (x);
alert (this.x);
Method2 ();
}
This.method3 = function () {
Method1 ();
}
}

Test
var o = new Subclass ();

Alert (o instanceof parentclass); False
Alert (o instanceof Subclass); True

alert (o.constructor); function Subclass () {...}

O.method1 (); I ' m a parentclass field!
I ' m a subclass object field!
I ' m a parentclass field!
I ' m a parentclass method!
O.METHOD2 (); I ' m a subclass field!
I ' m a subclass object field!
I ' m a subclass field!
I ' m a subclass method!

O.method (); Error!!!
O.method3 (); Error!!!
Subclass.staticmethod (); Error!!!

The above example is a good illustration of how inheritance is implemented using call inheritance.

The key to invoking inheritance is a single-step operation:

That is, when the child class is defined, the child class's this pointer is passed in by the call method of the parent class. Causes the parent class method to execute in the context of the child class.

In this way, all public instance members in the parent class that are defined by this method inside the parent class are inherited by the quilt class.

when judged by the instanceof operator, the instantiated object of the subclass belongs only to the subclass, not to the parent class.

When you view the constructor property of an instantiated object for a subclass, you see the definition of the subclass, not the definition of its parent class.

Next, the result of the call to O.method1 () and O.METHOD2 () is the same as the result of the prototype inheritance method, and the same problem is not repeated here.

By the result of the call to O.method () we see that the method defined on the parent class prototype is not inherited by the quilt class.

With the result of the call to O.METHOD3 () we see that the instance methods defined in the subclass also cannot access private instance members defined in the parent class.

Finally, with the result of the call to Subclass.staticmethod () we see that static members are also not inherited.

Finally, there is one point that is not reflected in this example, that is, by invoking the inheritance method, multiple inheritance can be achieved. That is, a subclass can inherit from more than one parent class all public instance members defined within the parent class by this method.

As a weakly typed language, JavaScript provides rich polymorphism, and JavaScript polymorphism is not comparable to other strongly typed object-oriented languages. Polymorphic Overloads and Overrides

Let's start by explaining the difference between overloading and overwriting. The overloaded English is overload, and the English overlay is the override. It is not right to find that most people on the Internet take override as an overload. There is a difference between overloading and overwriting.

Overloading means that functions of the same name (note that this includes functions) or methods can have multiple implementations, and they rely on the type of the parameter and/or the number of arguments to differentiate the recognition.

Overriding means that a subclass can define a method that has the same name as the parent class, with the same parameter type and number, which, after the definition of the method, is hidden in the instantiated object of the subclass in which the parent class inherits the same name. Overload

The parameters of a function in JavaScript are of no type, and the number of arguments is arbitrary, for example, although you can define one:

function Add (A, b) {
return a + B;
}

Such a function, but you can still call it is to bring in any number of arguments, of course, the parameter type is also arbitrary. As to whether it is an error, it is determined by what is executed in the function, and JavaScript does not determine which function you are calling based on the number of arguments and the type of argument you specify.

Therefore, to define overloaded methods, you cannot do so in a strongly typed language. But you can still implement overloading. Is through the arguments property of the function. For example:

function Add () {
var sum = 0;
for (var i = 0; i < arguments.length; i++) {
Sum + = Arguments[i];
}
return sum;
}

This allows you to implement an overload of any number of parameter addition functions.

Of course, you can also use instanceof or constructor to determine the type of each parameter in a function to decide what to do later and implement more complex functions or method overloads. In short, the overloading of JavaScript is done in the function by the user by manipulating the arguments property. Covered

It is also easy to implement overrides, such as:

function ParentClass () {
This.method = function () {
Alert ("ParentClass method");
}
}
function Subclass () {
This.method = function () {
Alert ("Subclass Method");
}
}
Subclass.prototype = new ParentClass ();
SubClass.prototype.constructor = subclass;

var o = new Subclass ();
O.method ();

In this way, the method defined in the subclass overrides the methods inherited from the parent class.

You might say that this is a good overlay, but in Java, the overridden method can call the overridden method (the parent class method), and how do you do it here? It's also easy, and more flexible than Java, limitations in Java, you can only use super to invoke the overridden method in a method that overrides the overridden method. Not only can we achieve this, but we can also make it possible for all methods in a subclass to invoke methods that are overridden in the parent class. Look at the following example:

    1. function ParentClass () {
      This.method = function () {
      Alert ("ParentClass method");
      }
      }
      function Subclass () {
      var method = This.method;
      This.method = function () {
      Method.call (this);
      Alert ("Subclass Method");
      }
      }
      Subclass.prototype = new ParentClass ();
      SubClass.prototype.constructor = subclass;

      var o = new Subclass ();
      O.method ();

You will find that it is so simple to define a private variable before defining the override method, and then assign it to the method defined in the parent class that will be overridden, and then we can continue to invoke it later, and this method is private and is not visible to the object of the subclass. This is consistent with the overrides of other high-level language implementations.

Finally, we need to note that when we invoke this method in the override method, we need to use the call method to change the execution context to this (although not necessary in this case), and if this method is called directly, the execution context becomes the global object.

JavaScript Object-oriented programming (bottom)--Inheritance and polymorphism "go"

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.