This is the 9th day of my participation in Gwen Challenge

First, define a class

function Animal (name) {
  / / property
  this.name = name || 'Animal';
  // Instance method
  this.sleep = function(){
    console.log(this.name + 'Sleeping'); }}// Prototype method
Animal.prototype.eat = function(food) {
  console.log(this.name + 'Eating:' + food);
};
Copy the code

1. Prototype chain inheritance

Idea: Inheritance is implemented using a stereotype chain, with an instance of a superclass as the stereotype of a subclass

function Dog(){ }
Dog.prototype = new Animal();
Dog.prototype.name = 'dog';

var dog = new Dog();

console.log(dog.name); / / the dog
dog.eat('dog food'); // The dog is eating dog food
dog.sleep(); // The dog is sleeping
console.log(dog instanceof Animal);  // true 
console.log(dog instanceof Dog);  // true
Copy the code

Features:

  1. Very pure inheritance, where an instance is an instance of a subclass and an instance of a parent class;
  2. New prototype methods/attributes in the parent class, accessible to all subclasses;
  3. Simple and easy to implement;

Disadvantages:

  1. You can add instance attributes to Dog instances in the Dog constructor. If new prototype properties and methods are added, they must be executed after statements such as new Animal();
  2. Multiple inheritance cannot be realized;
  3. All attributes from the stereotype object are shared by all instances;
  4. Cannot pass arguments to the parent constructor when creating a subclass instance.

Constructor inheritance

Idea: Add instances of subclasses using the parent class’s constructor by executing constructors on newly created objects using the call, apply methods

function Dog(name){
  Animal.call(this);
  this.name = name || 'wang wang';
}

var dog = new Dog();

console.log(dog.name); / / wang wang
dog.sleep(); // Wang Wang is sleeping
console.log(dog instanceof Animal); // false
console.log(dog instanceof Dog); // true
Copy the code

Features:

  1. In method 1, the subclass instance shares the parent class reference attribute.
  2. When creating a subclass instance, you can pass arguments to the parent class;
  3. Multiple inheritance can be implemented (call multiple parent objects);

Disadvantages:

  1. An instance is not an instance of a parent class, only an instance of a subclass;
  2. Only instance attributes and methods of the parent class can be inherited, not stereotype attributes/methods.
  3. Function reuse cannot be realized, each subclass has a copy of the parent class instance function, affecting performance;

3. Instance inheritance

Idea: Add a new feature to a parent class instance and return it as a subclass instance

function Dog(name){
  var instance = new Animal();
  instance.name = name || 'wang wang';
  return instance;
}

var dog = new Dog();

console.log(dog.name); / / wang wang
dog.sleep(); // Wang Wang is sleeping
console.log(dog instanceof Animal); // true
console.log(dog instanceof Dog); // false
Copy the code

Features:

  1. There is no limit to how the call is made, and whether a new subclass () or subclass () returns the same object;

Disadvantages:

  1. An instance is an instance of a parent class, not a subclass;
  2. Multiple inheritance is not supported;

4. Copy inheritance

function Dog(name){
  var animal = new Animal();
  for(var p in animal){
    Dog.prototype[p] = animal[p];
  }
  Dog.prototype.name = name || 'wang wang';
}

var dog = new Dog();
console.log(dog.name); // 'bark'
dog.sleep(); // Wang Wang is sleeping
console.log(dog instanceof Animal); // false
console.log(dog instanceof Dog); // true
Copy the code

Features:

  1. Support multiple inheritance;

Disadvantages:

  1. Low efficiency and high memory footprint (due to copying parent class attributes);
  2. Unable to get non-enumerable methods of the parent class (non-enumerable methods, not accessible using for in);

5. Original type inheritance

Idea: You don’t need to define a class to adopt old-style inheritance!! , passing in the argument obj, generates an object that inherits obj object

var animal = {
  name: "Wang wang".age: 2,}function F(o) {
  function C() {}
  C.prototype = o;
  return new C();
}

var dog = F(animal)
console.log(dog.name); / / wang wang
console.log(dog.age); / / 2
Copy the code

Features:

  1. Generate an object that inherits from an object directly from an object;

Disadvantages:

  1. It’s not class inheritance, it’s prototypal foundation, it lacks the concept of class;

6. Composite Inheritance (recommended)

Idea: Use construction inheritance and prototype chain composition

function Dog(name){
  Animal.call(this);
  this.name = name || 'wang wang';
}

Dog.prototype = new Animal();
Dog.prototype.constructor = Dog;

var dog = new Dog();

console.log(dog.name); / / wang wang
dog.sleep(); // Wang Wang is sleeping
console.log(dog instanceof Animal); // true
console.log(dog instanceof Dog); // true
Copy the code

Features:

  1. It makes up for the defect of mode 2 by inheriting instance attributes/methods as well as prototype attributes/methods.
  2. Is an instance of both a subclass and a superclass;
  3. There is no reference attribute sharing problem;
  4. Can pass parameter;
  5. Function reusable;

Disadvantages:

  1. The parent constructor is called twice, generating two instances (the subclass instance masks the subclass prototype);

Parasitic inheritance

Idea: the original type + factory pattern solves the problem of combining inheritance to call the constructor twice; Create a function that simply encapsulates the inheritance process, then internally enhance the object in some way, and finally return the object;

// temporary transfer function
function obj(o) {
  function Animal() {}
  Animal.prototype = o;
  return new Animal();
}

// Parasitic function
function create(o){
  var Dog = obj(o);
	// F can be extended
  Dog.sleep = function(){
  	console.log(this.name + 'Sleeping')}return Dog;
}

var mydog = {
  name: 'wang wang'.age: 1};var dog = create(mydog);

console.log(dog.name); / / wang wang
dog.sleep(); // Wang Wang is sleeping
Copy the code

Features:

  1. An extension of the original type inheritance

Disadvantages:

  1. There is still no concept of classes

8. Parasitic combination Inheritance (recommended)

Idea: The combination of parasitic inheritance and combined inheritance, perfect realization of inheritance without two superclass attributes

// This implementation does not fix constructor
function Dog(name){
  Animal.call(this);
  this.name = name || 'wang wang';
}
(function(){
  // Create a class with no instance methods
  var Super = function(){};
  Super.prototype = Animal.prototype;
  // Use the instance as the prototype of the subclass
  Dog.prototype = newSuper(); }) ();var dog = new Dog();

console.log(dog.name); / / wang wang
dog.sleep(); // Wang Wang is sleeping
console.log(dog instanceof Animal); // true
console.log(dog instanceof Dog); // true
Copy the code

Supplement:

// Define a class
function Animal (name) {
  / / property
  this.name = name || 'Animal';
  // Instance method
  this.sleep = function(){
    console.log(this.name + 'Sleeping');
  }
  // Instance references attributes
  this.features = [];
}

function Dog(name){}
Dog.prototype = new Animal();

var tom = new Dog('Tom');
var kissy = new Dog('Kissy');

console.log(tom.name); // "Animal"
console.log(kissy.name); // "Animal"
console.log(tom.features); / / []
console.log(kissy.features); / / []

tom.name = 'Tom-New Name';
tom.features.push('eat');

// Changes to members of the parent instance value type are not affected
console.log(tom.name); // "Tom-New Name"
console.log(kissy.name); // "Animal"

// Changes that reference a type member to a parent instance can affect other subclass instances
console.log(tom.features); // ['eat']
console.log(kissy.features); // ['eat']

// Cause analysis:

// 1. Execute Tom.features. push, first find the instance property of Tom object (not found), then go to the prototype object, i.e. If yes, insert values directly into the features property of the object.
/ / 2. In the console. The log (kissy. The features); From time to time. Ditto, not on the Kissy instance, so look for the prototype.
// 3. If the features attribute is present in the prototype object, it will be returned directly, but note that the features attribute value has been changed.
Copy the code

Features:

  1. Perfect;

Disadvantages:

  1. The implementation is complex;

9. Inheritance in ES6 (highly recommended)

The idea: ES6 inheritance through the syntactic sugar Class and Java and other object-oriented languages in the implementation of inheritance is very similar, but syntactic level of course, the essence of course is still through the prototype implementation. ES6 implements inheritance through the extends and super keywords, just like the object-oriented Java language.

class Animal{
  constructor(name,age){
    this.name = name || 'Animal';
    this.age = age
    this.hobbies = ['sleep'.'eat']}/* This is equivalent to the method hanging on the prototype */
  static say(){ // Add a static method to the class
    console.log('hello');
  } // Do not place commas between methods
  getname(){
    console.log(this.name); }}class Dog extends Animal{
	Subclass-specific attributes are written in front of arguments and superclass attributes are placed behind. arg ... An arG puts the extra arguments in a function into an array. * /
  constructor(food,... arg){
    super(... arg);// It is equivalent to calling the parent class and putting the extra parameters (attributes of the same parent class) into super to achieve the purpose of inheriting the attributes of the parent class
    /* In inheritance, constructor must write under super super to use this. Super has a temporary deadband */
    this.food = food
  }
  static sayState(){
    console.log("I'm sleeping.")}sayAge(){
    console.log("My year" + this.age + ', ');
  }
  sayFood(){
  	console.log('I'm eating.'+this.food)
  }
}

var dog1 = new Dog('bone'."Wang wang".2);

Animal.say() / / how are you
Dog.sayState();  // I am sleeping

dog1.getname();  / / wang wang
dog1.sayAge(); // I am 2 years old
dog1.sayFood(); // I'm eating a bone

var dog2 = new Dog('dog food'."Prosperous wealth.".1);
dog2.hobbies.push("Play");

dog2.getname();  / / prosperous wealth
dog2.sayAge(); // I am 1 years old
dog2.sayFood(); // I'm eating dog food

console.log(dog1.hobbies)  // [' sleep ',' eat ']
console.log(dog2.hobbies)  // [' sleep ',' eat ',' play ']
Copy the code