js prototype and inheritance

Posted by timbo6585 on Sat, 16 Oct 2021 11:20:31 +0200

Because I learned java inheritance and didn't have class es and extensions before es6, I couldn't understand prototypes for several days. I just saw Ruan Yifeng's article and seemed to have an epiphany. Record it.
Big guy article:
http://www.ruanyifeng.com/blog/2011/06/designing_ideas_of_inheritance_mechanism_in_javascript.html

  1. When C + + and Java use the new command, the constructor of the "class" will be called. He made a simplified design. In Javascript language, the new command is not followed by a class, but a constructor.
    loot at this
		let fn = function() {
            this.a = 1;
            this.b = 2;
        }
        let obj = new fn();
  1. One disadvantage of using constructors to generate instance objects is that properties and methods cannot be shared. For example, in the constructor of a DOG object, set the common property categories of an instance object.
function DOG(name){

    this.name = name;

    this.species = 'Canidae';

  }

//Then, two instance objects are generated:

  var dogA = new DOG('Big hair');

  var dogB = new DOG('twenty fen');

//The categories attribute of the two objects is independent. Modifying one of them will not affect the other.

  dogA.species = 'Felidae';

  alert(dogB.species); // Display "canine", not affected by dogA

With this in mind, Brendan Eich decided to set a prototype attribute for the constructor.

This attribute contains an object (hereinafter referred to as "prototype object"), and the attributes and methods that all instance objects need to share are placed in this object; Those properties and methods that do not need to be shared are placed in the constructor.

Once the instance object is created, it will automatically reference the properties and methods of the prototype object. In other words, the properties and methods of instance objects are divided into two types: one is local and the other is referenced.

function DOG(name){

    this.name = name;

  }
  DOG.prototype = { species : 'Canidae' };
  var dogA = new DOG('Big hair');
  var dogB = new DOG('twenty fen');
  alert(dogA.species); // Canidae
  alert(dogB.species); // Canidae
//Now, the categories attribute is placed in the prototype object and shared by the two instance objects.
//As long as the prototype object is modified, two instance objects will be affected at the same time.
  DOG.prototype.species = 'Felidae';
  alert(dogA.species); // Felidae
  alert(dogB.species); // Felidae

The above is Fengge's code and thinking.

Now there's a disgusting place
Constructor, prototype_ proto_, Instance object,
If you understand the relationship between these, you will understand the prototype chain.


<script>
        //Prototype: prototype; Rudiments; Initial form
        let Person = function() {
            this.a = 1;
            this.b = 2;
        }
        let person1 = new Person();
        Person.prototype.age = 21;
        console.log(person1);
        console.log(person1.constructor); //f(){this.a = 1;this.b = 2;}
        console.log(Person.prototype); //{constructor:f}
        console.log(person1.__proto__); //{constructor:f}
        console.log(person1.__proto__ === Person.prototype); //true
        console.log(Person); //f(){this.a = 1;this.b = 2;}
    </script>

Print instance object:

Keep looking

According to what brother Feng said above, combined with his own understanding.

  1. There is a prototype object in the constructor to store some public properties.
  2. The instance object will store two things, one is to announce the local properties and methods obtained from the constructor, and the other is__ proto__ The reference points to the Prototype object in the constructor. (different browsers also call it [[Prototype]])
  3. The prototype is owned by the constructor. The prototype Object has the properties or methods you set. The constructor points to (that is, the constructor Person ()), proto, and references the prototype Object of the Object pointing to the prototype. Finally, it is the prototype Object of the Object, and the prototype Object of the Object is null.
  4. This is the prototype chain I understand.

Finally, I understand a little. It's too delicious. Next, there are all kinds of inheritance implementations.
Why are there several inheritance methods?
Remember that there are several ways to create a javascript.
Literal quantity, constructor, created by object, es6 class, etc

  1. Constructor
    Change this point of the constructor of Animal through apply.
		function Animal() {    
            this.species = "animal";  
        }

        function Cat(name, color) {   
            Animal.apply(this, arguments) 
            this.name = name;
            this.color = color;
        }
        let cat1 = new Cat('Big flower', 'black');
        console.log(cat1.species); //animal
  1. prototype:
    2.1 the child prototype points to the parent instance object
		function Animal() {    
            this.species = "animal";  
        }

        function Dog(name, color) {
            this.name = name;
            this.color = color;
        }

        Dog.prototype = new Animal();
        Dog.prototype.constructor = Dog; //Without this line, Dog's prototype object has no constructor
        let dog = new Dog("Da Wang", 'white')
        console.log(dog);

Why do you need this: Dog.prototype.constructor = Dog;
The prototype object has a constructor pointing to the constructor
The instance object also has a constructor pointing to the constructor of the prototype object. If it is not written, the prototype chain may be confused.
continue;
2.2 child prototype points to parent prototype

   <script>
        function Animal() {     }

        function Dog(name, color) {
            this.name = name;
            this.color = color;
        }
        Animal.prototype.speices = 'animal';
        Dog.prototype = Animal.prototype;
        Dog.prototype.constructor = Dog;
        let dog = new Dog("twenty fen", "black")
        console.log(dog);
        console.log(Animal.prototype.constructor);//Dog
    </script>

Dog's prototype object points to Animal. Without the new Animal object, memory will not be saved,
but, bind the prototype object of Animal to Dog. Last line above.

2.3 through empty objects, the combination of the above two, that is, saving memory, does not have two prototype bindings.

     function Animal() {}

        function Cat(name, color) {
            this.name = name;
            this.color = color;
        }

        Animal.prototype.species = "animal"
        var F = function() {};
        F.prototype = Animal.prototype; 
        Cat.prototype = new F();  
        Cat.prototype.constructor = Cat;

        let cat = new Cat('tearful', 'white')
        alert(cat.species)

Final version:

 function extend(Child, Parent) {

    var F = function(){};

    F.prototype = Parent.prototype;

    Child.prototype = new F();

    Child.prototype.constructor = Child;

    Child.uber = Parent.prototype;
    //Open a mouth for standby to realize the completeness of inheritance. It's not written in yui

}
  1. Implementation of non constructor:
    3.1 object(o) function

Douglas Crockford, inventor of json format, proposed an object() function.

	function object(o) {

    function F() {}

    F.prototype = o;

    return new F();

  }

3.2 deep and shallow copy, copy all the attributes, that's inheritance, air shaking cold (used by JQuery)
Shallow:

		function extendCopy(o){
            let c = {}
            Object.keys(o).forEach(key=>{
                c[key] = o[key];//es6 is too lazy to write es5
            })
            c.uber = o;
            return c;
        }

	 function deepCopy(o,c){
            let c = c || {}
            Object.keys(o).forEach(key=>{
                if(typeof o[key] ==="object"){
                    deepCopy(o[key],c[key]);
                }
                else{
                    c[key]=o[key];
                }
            })
            return c;
        }

The depth copy principle can be seen Last

  1. es6 extensions finally came to es6 and cried

Standard writing:

class A {}

class B extends A {
  constructor() {
    super();
  }
}

Just pay attention to the following points:

  1. The subclass constructor must call super()//java

This is because the subclass's own this object must first be molded through the constructor of the parent class to obtain the same instance properties and methods as the parent class, and then process it, plus the subclass's own instance properties and methods. If you do not call the super method, the subclass will not get the this object.

  1. es5 6 differences

The essence of inheritance in ES5 is to first create the instance object this of the subclass, and then add the methods of the parent class to this (Parent.apply(this)). ES6
The inheritance mechanism of is completely different. The essence is to add the properties and methods of the parent instance object to this (so you must call the super method first), and then modify this with the constructor of the subclass.

reference resources:
https://es6.ruanyifeng.com/#docs/class-extends
https://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_inheritance_continued.html
https://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_inheritance.html
Peak boss yyds

Topics: Javascript ECMAScript