Implementation methods and differences of class-type inheritance and prototype inheritance in JavaScript

Source: Internet
Author: User

In all object-oriented programming, inheritance is an important topic. In general, when designing classes, we want to reduce repetitive code and try to weaken the coupling between objects (allowing one class to inherit another can lead to strong coupling). With regard to "decoupling" is another important topic in programming, this article focuses on how to implement inheritance in JavaScript.

Other object-oriented programming languages use keywords to solve inherited problems (such as extend or inherit). But there is no mechanism in JavaScript that defines this implementation, and if a class needs to inherit another class, the process of inheriting it requires the programmer to implement it by itself.

Implementation of class-type inheritance

1, the way to create a class:

1 //defining constructors for classes2 functionPerson (name) {3      This. Name = Name | | ' Default name ';4 }5 //public methods that define all instances of the class6Person.prototype.getName =function() {7     return  This. Name;8 }9 Ten varSmith =NewPerson (' Smith '); One varJacky =NewPerson (' Jacky '); A  -Console.log (Smith.getname (), Jacky.getname ());//Smith Jacky

2, inherit this class: this needs to be implemented in two steps, the 1th step is to inherit the attributes defined in the parent class constructor, and the 2nd step is to inherit the prototype property of the parent class.

//defining constructors for classesfunctionPerson (name) { This. Name = Name | | ' Default name ';}//public methods that define all instances of the classPerson.prototype.getName =function() {    return  This. Name;functionAuthor (name, books) {//inherit the properties defined in the parent class constructor    //inherit by changing the execution context of the parent class constructorPerson.call ( This, name);  This. Books =Books;}//inherit the method corresponding to the parent classAuthor.prototype =NewPerson ();//Author.prototype.constructor = = personAuthor.prototype.constructor = Author;//fixed constructor loss caused by modifying prototype chainAuthor.prototype.getBooks =function() {    return  This. Books;};//TestvarSmith =NewPerson (' Smith ');varJacky =NewAuthor (' Jacky ', [' Booka ', ' BOOKB ']); Console.log (Smith.getname ()); //SmithConsole.log (Jacky.getname ());//JackyConsole.log (Jacky.getbooks (). Join (', '));//Booka, BOOKBConsole.log (Smith.getbooks (). Join (', '));//uncaught TypeError:smith.getBooks is not a function

As you can see from the test results, author correctly inherits the person and modifies the author's prototype without affecting the person. The key to this is Author.prototype = new person (), which distinguishes it from author.prototype = Person.prototype. The former produces an example that has a copy of the Person.prototype (which is understood here first, followed by a more detailed analysis ). The latter refers to the prototype of the two points to the same prototype object.

Well, this also means that each inheritance will produce a copy of the parent class, which is definitely consuming the memory, but for class inheritance this memory overhead must be paid, but it can be done more: Author.prototype = new Person () This sentence actually executes the constructor one at a time (and this time it can only be executed in the subclass constructor), especially when the parent class's constructor is very large and time consuming and memory. Modify the way you inherit, as follows:

Author.prototype = (function() {    function  F () {}    = person.prototype;     returnnew  F ();}) ();

The code shown above, new, removes the call to the parent class's constructor, saving the cost of one call.

3. The class inheritance is characterized by the subclass executing the constructor of the parent class once every time the object is instantiated . If E inherits the D,d inherits the C,c inherits the B,b inherits a, when instantiates an e, altogether passes through several constructors the call?

/*functions for inheriting methods*/functionextend (son, father) {functionF () {} F.prototype=Father.prototype; Son.prototype=NewF (); Son.prototype.constructor=Son;}//Class AfunctionA () {Console.log (' A () ');} A.prototype.hello=function() {Console.log (' Hello, world. ');}//Class BfunctionB () {A.call ( This); Console.log (' B () ');} Extend (B, A);//Class CfunctionC () {B.call ( This); Console.log (' C () ');} Extend (C, B);//Class DfunctionD () {C.call ( This); Console.log (' D () ');} Extend (D, C);//Class EfunctionE () {D.call ( This); Console.log (' E () ');} Extend (E, D);//Create an instance of EvarE =NewE ();//A () B () C () D () E ()E.hello ();//Hello, world.

5 times, this is just the number of times to instantiate an E call. Therefore, we should reduce the level of inheritance as much as possible. This is not to say that you should not use this type of inheritance, but rather to decide what method to use based on your application.

Second, the original type of inheritance

1, first look at a piece of code: We first change the previous class inheritance prototype that section to another function clone, and then through the literal creation of a person, and finally let author into Person's clone.

//This function can be understood as cloning an objectfunctionClone (object) {functionF () {} F.prototype=object; return NewF ();}varperson ={name:' Default Name '; GetName:function() {        return  This. Name; }}//Next, let the author become the clone of person.varAuthor = Clone (person);

Ask a question: Does new F () in the Clone function open up memory space for this instance to store a copy of the object?

According to my previous understanding, the answer is yes. But when I continue to write the code down, something strange happens and the code looks like this:

//Next, let the author become the clone of person.varAuthor =Clone (person); Author.books= []; Author.getbooks=function() {    return  This. Books.join (', ');}//Add an author SmithvarSmith =Clone (Author); Console.log (Smith.getname (), Smith.getbooks ());//Default NameSmith.name = ' Smith '; Smith.books.push (' <<book a>> ', ' <<book b>> ');//The author has written two booksConsole.log (Smith.getname (), Smith.getbooks ());//Smith <<book a>>, <<book b>>//Add one more author JackyvarJacky =Clone (Author); Console.log (Jacky.getname (), Jacky.getbooks ());//Default Name <<book a>>, <<book b>>

When we continue to increase the author Jacky, Strange phenomenon happened!! Jacky's name is still the default name, but he also wrote two books like Smith? Jacky's books haven't been push yet. Here, I think of the case of referencing an object (when referencing an object, referring to the memory address of the object), the problem is definitely in the clone () function of the new F () here.

In fact, the new F () in this clone actually returns the object that owns all the properties of the cloned object. However, these properties retain a reference to the corresponding property in the cloned object, rather than a completely separate copy of the property. In other words, the properties of the new object point to the same memory address as the property of the object being cloned (students who have studied C should understand the pointer type, which is similar in meaning).

So why is the Jacky book the same as Smith's book in the above code, and why Jacky's name is not Smith but the default name? This is the mechanism of inheritance in JavaScript, and when Smith has just inherited from author, his attributes retain a reference to the properties of author, and once we display the re-assignment of the properties of Smith, The JAVASCRITP engine will give Smith the property to re-partition the memory space to store the corresponding value, because of the re-partition of the address, then the smith.name will not affect the rewriting of author.name. This is a good explanation of the previous question-why Jacky's name is not Smith but the default name.

2, based on the prototype inheritance

By analyzing the previous situation, it can be seen that the method based on prototype inheritance can save memory more (only when it is necessary to open up new memory space). Note, however, that the properties of an object must be re-assigned (re-dividing the memory) when it is based on prototype inheritance, and then the property is referenced. For the method of the object, if there are different ways of handling it, we just need to redefine it.

Here is a complete, correct example of the previous code to illustrate the characteristics and usage of the prototype inheritance:

//This function can be understood as cloning an objectfunctionClone (object) {functionF () {} F.prototype=object; return NewF ();}varperson ={name:' Default Name ', GetName:function() {        return  This. Name; }}//Next, let the author become the clone of person.varAuthor =Clone (person); Author.books= []; Author.getbooks=function() {    return  This. Books.join (', ');}//Add an author SmithvarSmith =Clone (Author); Smith.name= ' Smith '; Smith.books= []; Smith.books.push (' <<book a>> ', ' <<book b>> ');//The author has written two booksConsole.log (Smith.getname (), Smith.getbooks ());//Smith <<book a>>, <<book b>>//Add one more author JackyvarJacky =Clone (Author); Jacky.name= ' Jacky '; Jacky.books= []; Jacky.books.push (' <<book c>> ', ' <<book d>> '); Console.log (Jacky.getname (), Jacky.getbooks ()); //Jacky <<book c>>, <<book d>>
The difference between the class-type inheritance and the primitive inheritance and the phase-style

1. In class inheritance: Use constructors to initialize the properties of an object, inheriting these properties by calling the constructor of the parent class. The method is inherited by the prototype of the new parent class.

2, prototype inheritance: removed the constructor, but need to write the properties and methods of the object {} declaration. To be exact, the prototype inheritance is the prototype method that inherits the parent class in the class-style inheritance.

Implementation methods and differences of class-type inheritance and prototype inheritance in JavaScript

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.