Object-oriented programming: inheritance, encapsulation, polymorphism.

Object inheritance: By inheriting from OBJECT B, object A directly owns all properties and methods of object B. This is very useful for code reuse.

In classic object-oriented languages, you might prefer to define class objects, and then you can simply define which classes inherit which classes (see some simple examples in C++ inheritance). JavaScript uses a different set of implementations where inherited object functions are not copied, but inherited through a chain of archetypes

Review: JavascriptJS Prototypes and Prototype Chains and Inheritance issues

What is a prototypical language

  1. Only objects, no classes; Objects inherit from objects, not classes inherit from classes.

  2. The “prototype object” is the core concept. A stereotype object is a template for a new object that shares its properties with the new object. An object can enjoy not only the properties defined at its own creation time and runtime, but also the properties of the prototype object.

  3. Each object has its own prototype object, and all objects form a hierarchical tree system. The top level object of the root node is a language-native object, which has no archetype and whose properties all other objects inherit directly or indirectly.

Prototyping is a two-step process

  1. Generate new objects using “prototype objects” as “templates” : this step is necessary because it is the only way each object is born. Create objects from prototypes. That’s what prototypes are for.

  2. Initialize internal properties: This step is not necessary. In plain English, that is, if we are not satisfied with the “copy”, we can “reprocess” it to acquire a “personality” different from the “template”.

So in the world of JavaScript, the idea that everything is an object is always there.

There is no such thing as a class in JavaScript, and while classes in ES6 look like classes, they are really just syntactic sugar in ES5

Function People (name) {/ / attribute this. Name = name | | this. Annie / / instance methods sleep = function () {the console. The log (enclosing the name + 'sleeping')}} // prototype method people.prototype. eat = function(food){console.log(this.name + 'eating:' + food); }Copy the code

The basic approach to JavaScript, first and foremost, is prototype inheritance

Prototype chain inheritance

An instance of a parent class acts as a prototype for a subclass

function Woman(){ this.name= "SubType"; Woman.prototype= new People(); woman.prototype = new People(); woman.prototype = new People(); // When we instantiate a People, we actually perform two steps // 1. The newly created object copies all the attributes and methods in the parent constructor // 2. Name = 'haixia'; woman.prototype. name = 'haixia'; // Woman.prototype.name = ()=>{}; WomanObj = new Woman();Copy the code

Advantages of prototype chain inheritance:

  • New stereotype methods/attributes in the parent class that are accessible to all subclasses

  • Very pure inheritance, an instance is an instance of a subclass and an instance of a parent class

  • Simple and easy to implement

Disadvantages of prototype chain inheritance:

  1. You can add instance attributes to a subclass, but you need to add new stereotype attributes and methods after the new parent constructor

  2. Multiple inheritance cannot be implemented

  3. ** All attributes from the stereotype object are shared by all instances, and ** subclasses can override methods on the parent stereotype

  4. When creating a subclass instance, you cannot pass arguments to the superclass constructor

Woman. Prototype = new People();

  • The constructor attribute is missing from the heap, causing the class’s prototype constructor to be missing (fix: manually add constructor attribute to heap).

  • After the prototype to redirect, the default browser open up the prototype heap memory will be released, if already stored before some methods or properties, these things will be lost (so: built-in prototype of a class is not allowed to redirect to channel out their own heap memory, because the built-in classes on bringing many properties method, redirect after all didn’t, so is not allowed)

The prototype inherits the classic pen test questions

function Parent () {
  this.a = 1;
  this.b = [1, 2, this.a];
  this.c = {demo: 5};
  this.show = function () {
    console.log(this.a + ' ' + this.c.demo + ':' + this.b + '\n');
  };
}

function Child () {
  this.a = 2;
  this.change = function () {
    this.b.push(this.a);
    this.a = this.b.length;
    this.c.demo = this.a++;
  };
}

Child.prototype = new Parent();
var parent = new Parent();
var child1 = new Child();
var child2 = new Child();
child1.a = 11;
child2.a = 12;
child1.change();
child2.change();
parent.show();
child1.show();
child2.show();
Copy the code

Think about common problems with prototypes

Classic inherit

function extendObj(obj) { if (Object.create) { return Object.create(obj) } else { function F () { } F.prototype = obj; return new F() } } var obj = { name: "smd", age: 26, sayHi: function () { } } var newObj = createObj(obj) /* Extend Function */ function extend(subClass,superClass){ var Func = function(){} ; Func.prototype = superClass.prototype ; subClass.prototype = new Func() ; subClass.prototype.constructor = subClass ; };Copy the code

NewObj inherits obj’s properties and methods, but also suffers from the problem of sharing referenced type properties in parent classes

Instance inheritance (original type inheritance)

function Wonman(name){ let instance = new People(); instance.name = name || 'wangxiaoxia'; return instance; } let wonmanObj = new Wonman(); Function People (name) {this.colors = ["red", "blue", "green"]; this.name = name; Prototype = function () {return this.name; }; Function Woman (name, subName) {people.call (this, name); // Call the constructor for People and pass this. SubName = subName; } /** Step 2 */ // Resolve the problem that call cannot inherit the parent prototype properties/methods // object.create method receives an Object as the prototype of the newly created Object, // Any property specified by this method overwrites the property of the same name on the prototype Object. Prototype = object.create (people.prototype, {constructor: {/ / note that specify Woman. Prototype. Constructor = value: the Woman Woman, enumerable: false, writable: true, configurable: true }, run : { value: function(){ // override People.prototype.run.apply(this, arguments); // call super // ... }, enumerable: true, configurable: true, writable: True}}) /** Step 3 */ / Solve Woman. The prototype. The constructor = = = the problem of People / / here, is specified in the previous step, there is no need to operation again. / / Woman prototype. The constructor = Woman; var instance = new Woman('An', 'sistenAn')Copy the code

Example inheritance benefits:

  • There is no restriction on how to call

  • Simple and easy to implement

Disadvantages of instance inheritance:

  • You can’t inherit multiple times

Copies of the inheritance

function Wonman (name) {
  let instance = new People();
  for (var p in instance) {
    Wonman.prototype[p] = instance[p];
  }
  Wonman.prototype.name=name||'Tom'
}

let wonmanObj = new Wonman();
Copy the code

Features:

  • Support for multiple inheritance

Disadvantages:

  • Low efficiency and high memory footprint (due to copying parent class attributes)

  • Unable to get non-enumerable methods of the parent class (non-enumerable methods, not accessible using for in)

Object impersonation inheritance

Function Woman(name, age) {function Woman(name, age) {function Woman(name, age) {function Woman(name, age) { This. Method = People; This.method (name); // Delete this. Method; // If this is subclass this.age = age; this.sayWorld = function() { alert(age); }}Copy the code

The rise of Call Apply is due to the impostor of objects

Borrowing constructor inheritance (fake object, classical inheritance)

Copy the instance properties of the parent class to the child class

  • Functions are simply objects that execute code in a particular environment, so apply/ Call is used here.

  • Using the constructor of the parent class to enhance the instance of the child class is equivalent to copying the instance properties of the parent class to the child class (without using the stereotype).

    Function Woman(name){// This extends to people.call (this); / / People. The call (this, ‘zhoulujun’); this.name = name || ‘andy’ } let womanObj = new Woman();

This calls the parent constructor’s this to a reference to the instantiation object of the subclass, resulting in all properties of the parent class being mounted to the instance of the subclass when the parent class executes.

But in this way, there is no way to inherit from the parent prototype, so function reuse is out of the question

Woman cannot inherit from Parent’s prototype object and does not really implement inheritance (partial inheritance)

Using constructors to inherit advantages:

  1. Resolved that subclass constructors pass arguments to superclass constructors

  2. Resolved the issue of subclass instances sharing parent class reference properties

  3. Multiple inheritance can be implemented (call or apply multiple parent classes)

Disadvantages of borrowing constructor inheritance:

  1. Methods are defined in constructors and cannot be reused

  2. You cannot inherit stereotype properties/methods, only instance properties and methods of the parent class

Combinatorial inheritance

Call the parent class constructor, inherit the attributes of the parent class, and reuse the function by using the parent class instance as the prototype of the subclass

function Woman(name,age){
  People.call(this,name,age)
}
Woman.prototype = new People();
Woman.prototype.constructor = Woman;
let wonmanObj = new Woman(ren,27);
wonmanObj.eat();
Copy the code

Disadvantages:

  • Because the parent class is called twice, two instances are generated

  • Prototype = new People()

  • The second time is when instantiating people.Call (this,name,age)

Advantages:

  • Functions can be reused

  • There is no reference attribute problem

  • You can inherit properties and methods, and you can inherit properties and methods of stereotypes

Parasitic combinatorial inheritance

Through the parasitic way to repair the deficiency of combined inheritance, perfect inheritance

Function Woman(name,age){// People. Call (this,name,age)} Woman. Prototype = Object. The create (People) prototype); (function(){// create an empty class function Super (){}; Super.prototype = People.prototype; Woman.prototype = new Super(); }) (); / / repair problem of constructors to Woman. The prototype. The constructor = Woman; let womanObj = new Woman();Copy the code

There are actually two executions

Es6 inheritance

// All methods defined in class are not enumerable. // All methods defined in class are not enumerable. // All methods defined in class are not enumerable. Class People{constructor(name='wang',age='27'){this.name = name; this.age = age; } eat(){console.log(' ${this.name} ${this.age} eat food ')}} // The super constructor is used to create this object of the parent class. // Subclasses must call the super method from the constructor method, otherwise they will get an error when creating a new instance. If a subclass does not define a constructor method, that method is added by default; any subclass has a constructor method, regardless of whether it is explicitly defined. class Woman extends People{ constructor(name = 'ren',age = '27'){ super(name, age); Eat (){super.eat()}} let wonmanObj=new Woman('xiaoxiami'); wonmanObj.eat();Copy the code

ES5 inheritance essentially creates an instance object of the subclass, this, and then adds the Parent class’s methods to this (parent.apply (this)).

ES6 has a completely different inheritance mechanism, essentially creating an instance object of the parent class, this (so the super method must be called first), and then modifying this with the constructor of the subclass.

/** * inherits * @param {*} subClass * @param {*} superClass */ function _inherits(subClass, superClass) { superClass || typeof superClass ! == "function" ) { throw new TypeError("Super expression must either be null or a function, not " +typeof superClass); } /** * object.create takes two arguments * specifying the prototype to create the Object * @param {*} target prototype * @param {*} add attributes */ subclass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: Ttf_subclass, / / ttf_subclass. Prototype. The constructor to ttf_subclass enumerable: false, / / constructor cannot be enumerated writable: true, configurable: true } }); /** * object.setProtoTypeof method * sets the __proto__ attribute of a subclass to point to the superClass * @param {*} subclass * @param {*} superClass */ if (superClass) {// Set the subclass's __proto__ to give the Child access to the parent static attribute Object.setProtoTypeof? Object.setPrototypeOf(subClass, superClass) : (subClass.__proto__ = superClass); }}Copy the code

Reference article:

Multiple ways of JavaScript deep inheritance and pros and cons #16 github.com/mqyqingfeng…

Inheritance in JavaScript developer.mozilla.org/zh-CN/docs/…

Common way of six kinds of inheritance segmentfault.com/a/119000001 JavaScript…

Js zhuanlan.zhihu.com/p/37735247 inherited several ways

Explaining the js implementation inheritance way of 7 kinds of cloud.tencent.com/developer/a…

Necessary for the front interview JS inherit way to summarize www.imooc.com/article/201…

Reprint the home station article “JavaScript: the implementation of inheritance way prototype language object inheritance object principle analysis”, please indicate the source: www.zhoulujun.cn/html/webfro…