Learn about JavaScript design patterns (inheritance) _javascript tips

Source: Internet
Author: User

1. Inherit

Inheritance in JavaScript is a very complex topic, more complex than any other object-oriented language in the inheritance. In most other object-oriented languages, inheriting a class requires only one keyword. Unlike them, a series of measures are needed to achieve the purpose of inheriting public members in JavaScript. What's more, JavaScript is one of the few languages that use archetypal inheritance. With the flexibility of this language, you can use standard, subclass-based inheritance, or you can use a more subtle prototype inheritance.

2. Why do I need to inherit?

In general, when designing a class, we want to reduce repetitive code and minimize coupling between objects. The use of inheritance conforms to the requirements of the previous design principle. With this mechanism, you can design on the basis of existing classes and take full advantage of the various methods that they already have, and make it easier to modify the design. Suppose you need to have several classes have a ToString () method that outputs the class structure in a specific way, and of course you can add the code for the definition ToString () method to each class in a copy-and-paste way, but if you do so, whenever you need to change the way this method works, You will have to repeat the same changes in each class. Conversely, if you provide a Tostringprovider class and then let those classes inherit the class, then the ToString method can only be declared in one place.

Having one class inherit from another may result in strong coupling between the two, which means that one class relies on an internal implementation of another class. We will discuss some techniques that can help to avoid this problem, including the technique of providing methods for other classes with the additive class.

3. Class-Based inheritance

Let's look at the following code:

<script type= "Text/javascript" > 


  function Person (name, age) 
  { 
   this.name = name; 
   This.age = age; 
  } 
  Person.prototype.say = function () 
  { 
   Console.log (this.name + "," + This.age); 
  } 
  function Student (No) 
  { 
   this.no = no; 
  } 
   the prototype of/** * Student to the object 
   */</span> 
  student.prototype = new Person (); 
  var stu1 = new Student ("0001"); 
  Stu1.name = ' John '; 
  Stu1.age = ' one '; 
  Console.log (stu1.no); 
  Stu1.say (); 
 </script> 

Output results:
John, 11
You can see Student successfully integrated the person, and has the person's say method, the core code is actually a sentence student.prototype = new person (), the following diagram to illustrate the principle:

The Student.prototype points to the new person (), and the new person's _proto_ points to the person Prototype, which completes the entire inheritance.

But there are problems with this approach:

Problem 1: when the parent class has a reference type variable that results in inconsistent data, we add a hobbies property to person, and the type is an array.

<script type= "Text/javascript" > 
  /** 
  * Problems 
  * 1, cannot pass parameters to the constructor method of the parent class in the student constructor 
  * 2, for reference type variables, Cause data inconsistency 


  /function person (name, age) 
  { 
   this.name = name; 
   This.age = age; 
   This.hobbies = []; 
  } 
  Person.prototype.say = function () 
  { 
   Console.log (this.name + "," + This.age + "," +this.hobbies); 
  } 
  function Student (NO) 
  { 
   this.no = no; 
  } 
  Student.prototype = new Person (); 

  var stu1 = new Student ("0001"); 
  Stu1.name = ' John '; 
  Stu1.age = ' one '; 
  Stu1.hobbies.push ("soccer"); 
  Stu1.say (); 

  var stu2 = new Student ("0002"); 
  Stu2.name = ' dick '; 
  Stu2.age = ' a '; 
  Stu2.hobbies.push ("Girl"); 
  Stu2.say (); 
 </script> 

Output results:
John, soccer.
Dick, Soccer,girl.
As you can see, Dick's hobbies should only be girl, but the above code lets all objects share the hobbies attribute.
There is also a problem with the above inheritance approach:

Issue 2: in the Student construction method, you cannot use the new Student ("00001", "John", 12); Create the object and initialize the name and age properties, and you must stu.name, stu.age to assign the value

To resolve the above problem, modify the above code:

 <script type= "Text/javascript" > Function person (name, age) {this.name = 
   Name 
   This.age = age; 
  This.hobbies = []; 
  } Person.prototype.say = function () {Console.log (THIS.name + "," + This.age + "," + this.hobbies); 
   function Student (name, age, NO) {/** * uses the call method, the first argument is the context; * Something like Super (name,age) in Java * * 
   Person.call (this, name, age); 
  this.no = no; 

  } Student.prototype = new person (); 
  var stu1 = new Student ("0001", "John", 11); 
  Stu1.hobbies.push ("soccer"); 

  Stu1.say (); 
  var stu2 = new Student ("0002", "Dick", 12); 
  Stu2.hobbies.push ("Cangjin"); 
  Stu2.hobbies.push ("basketball"); 
 Stu2.say (); </script> 

Output:
0001, John, soccer
0002, Dick, Cangjin,basketball
the Person.call (this,name,age) sense is used in the student constructor as the first parameter of "call" is context, and the shared problem of the reference property is resolved successfully. Perfect solution.

4, based on the prototype chain of inheritance

 <script type= "Text/javascript" >/** * All objects in the integration based on the prototype chain * problems: * 1, for reference type variables , resulting in inconsistent data * * * var person = {Name: "People", age:0, Hobbies: [], Say:function () {Console. 
    Log (THIS.name + "," + This.age + "," + this.hobbies); 

 } 
   } 
   ; 
 var Student = clone (person); 
 student.no = ""; 
 Student.sayhello = function () {Console.log (this.name + "Hello"); 
 var stu1 = Clone (Student); 
 Stu1.name = "Zhangsan"; 
 Stu1.age = 12; 
 Stu1.hobbies.push ("Java"); 

 Stu1.say (); 
 var stu2 = Clone (Student); 
 Stu2.name = "Lisi"; 
 Stu2.age = 13; 
 Stu2.hobbies.push ("Javascript"); 

 Stu2.say (); 
  /** * Returns an object prototype executing obj * @param obj * @returns {f}/function Clone (obj) {var F = function () 
  { 
  }; 
  F.prototype = obj; 

 return new F (); } </script> 

Output:
Zhangsan, Java
Lisi, Java,javascript
You can see that there is also a problem of inconsistent reference attributes, and the whole operation is based on the object, giving the feeling is not very good, the following diagram explained the principle:

Objects through a clone function, the constant return of a new object, and prototype execute the incoming object, the entire inheritance process is actually _proto_ constantly pointing to form a chain, so called the prototype chain.

Well, has been introduced, JS two ways of integration, the best use or through the inheritance of the class, relatively stable.

The above is about the inheritance of knowledge points related to the introduction, I hope to help you learn.

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.