JavaScript Prototype and Inheritance

Function prototypes in JavaScript are the basis for implementing inheritance.Prototype, construct, prototype chain, and inheritance based on prototype chain are important object-oriented content

prototype

  1. A prototype is an attribute of a function and an object

    function Car() {}
    console.log(typeof Car.prototype);
    console.log(Car.prototype);
    // object
    // {...}
  2. All objects constructed by the constructor have access to the properties and methods defined on the prototype

    function Car() {
     this.brand = "BMW";
     this.color = "red";
    }
    Car.prototype.price = "100 ten thousand";
    var car1 = new Car();
    var car2 = new Car();
    console.log(car1.price);
    console.log(car2.price);
    // 1 million
    // 1 million
  3. Inside the constructor and prototype define properties with the same name, and the instance object calls the properties in the constructor first

    function Car() {
     this.price = "10 ten thousand";
    }
    Car.prototype.price = "100 ten thousand";
    var car1 = new Car();
    console.log(car1.price);
    // 100,000
  4. Properties on prototype cannot be changed through an instance object

    function Car() {}
    Car.prototype.price = "100 ten thousand";
    var car1 = new Car();
    car1.price = "10 ten thousand";
    console.log(Car.prototype.price);
    // 1 million 

Typically, unchanged content or methods are placed under the prototype, which requires dynamic changes to be placed within the construction method and configured through parameters

constructor

  1. Constructor points to the constructor itself

    The constructor property of the instance object points to the constructor

    function Car() {}
    var car = new Car();
    console.log(car.constructor);
    console.log(Car)
    // Car(){}
    // Car(){}
  2. The constructor can be changed

    The constructor can be modified without affecting the instantiated object

    function Bike() {
     this.name = "bike";
    }
    Bike.prototype.name = "Bike";
    function Car() {}
    Car.prototype = {
     constructor: Bike
    }
    var car = new Car();
    console.log(Car.prototype);
    console.log(car.name);
    // {constructor: Bike(){}, ...} 
    // undefined

__proto__

  1. When the constructor is instantiated, mount its prototype under u proto_ of this within the function

    function Car() {}
    Car.prototype.name = "Jett";
    var car = new Car();
    console.log(Car.prototype);
    console.log(car.__proto__);
    // Car.prototype ->
    // {
    //   name: "Jett", 
    //   construct: Car(){}
    //   _proto_: {...}
    //   }
    // car._proto_ ->
    // {
    //   name: "Jett",
    //   construct: Car(){}
    //   _proto_: {...}          
    // }
    // 

    You can see that the printed Car.prototype and car. u proto_ are identical.Because when an object is instantiated, Car.prototype is mounted on this. u proto_ in the function, that is, on the u proto_ property of the instance object

    prototype is a property of the constructor, u proto_ belongs to each instance object and is an internal property that points to the same content

  2. The u proto_u property can be accessed through an instance object and modified

    function Car() {}
    Car.prototype.name = 'BWM';
    var car = new Car();
    console.log(car.name);
    car.__proto__= {
     name:"Benz"
    }
    console.log(car.name);
    // BWM
    // Benz

    You can also change the properties of the prototype to achieve results

    function Car() {}
    Car.prototype.name = 'BWM';
    var car = new Car();
    console.log(car.name);
    Car.prototype.name = 'Benz';
    console.log(car.name);
    // BWM
    // Benz

    However, reassigning a prototype does not affect previously instantiated objects

    function Car() {}
    Car.prototype.name = 'BWM';
    var car = new Car();
    console.log(car.name);
    Car.prototype = {
     name: "Benz"
    }    
    console.log(car.name);
    // BWM
    // BWM

    This is because reassignment is equivalent to creating a new object so that the prototype points to the new object, while the u proto_u attribute of the instance object still points to the original content, which is equivalent to two references to an object, one of which is not pointing to the object, but to the new object

    This does not affect objects that have already been instantiated, but it does affect objects that are subsequently instantiated because the modified prototype is mounted under the u proto_u property of the instance object during instantiation and points to the same object

Prototype Chain

  1. _u proto_u attribute in prototype

    function Car() {}
    var car = new Car();
    console.log(Car.prototype);

    When we print the prototype property of the constructor, we can see that

    {
     constructor: Car(),
     __proto__: {...}
    }

    There are also u proto_u attributes in the prototype, and the instantiation process protorype is mounted under u proto_u of the instance object, which means there is also a u proto_u attribute in the u proto_u of the instance object

    Because the prototype here is a non-empty object instantiated by a new Object() or other custom construction method, there is also a u proto_u attribute

  2. Chained u proto_u

    The prototype chain is a link made up of u proto_, and the top of the prototype chain is Object.prototype

    JuniorCoder.prototype.basicSkill = "html/css";
    function JuniorCoder() {
     this.lowerSkill = "javascript"
    }
    var junior = new JuniorCoder();
    SeniorCoder.prototype = junior;
    function SeniorCoder() {
     this.advancedSkill = "vue";
    }
    var senior = new SeniorCoder();
    console.log(senior);

    Here, the instance object of JuniorCoder() is assigned to SeniorCoder.prototype and printed out

    SeniorCoder {
     advcedSkill: "vue",
     __proto__: { // Senior. u proto_u, SeniorCoder.protoype
         lowerSkill: "javascript",
         __proto__: { // Junior. u proto_u, JuniorCoder.prototype
             basicSkill: "html/css",
             __proto__: { // Object.prototype
                 constructor: Object(),
                 toString: toString()
                 // ...
             }
         }
     }
    }

    As you can see, senior's u proto_u attribute points to JuniorCoder() instance junior, because junior was previously assigned to SeniorCoder.prototype

    In addition, junior's u proto_ points to an object, which is JuniorCoder.porotype, equivalent to the new Object(), so under junior's u proto_ is Object.prototype, which is the top of the prototype chain, where we can also see the String method and so on.

  3. Accessing properties on the prototype chain

    JuniorCoder.prototype.basicSkill = "html/css";
    JuniorCoder.prototype.sex = "man";
    function JuniorCoder() {
     this.lowerSkill = "javascript"
     this.age = 22;
    }
    var junior = new JuniorCoder();
    SeniorCoder.prototype = junior;
    function SeniorCoder() {
     this.advancedSkill = "vue";
    }
    var senior = new SeniorCoder();
    console.log(senior.age);
    console.log(senior.sex);
    // 22
    // man

    senior can access properties of junior itself or on JuniorCoder.prototype because junior is mounted on SeniorCoder.prototype

    JuniorCoder.prototype.basicSkill = "html/css";
    function JuniorCoder() {
     this.lowerSkill = "javascript";
     this.years = 3;
    }
    var junior = new JuniorCoder();
    SeniorCoder.prototype = junior;
    function SeniorCoder() {
     this.advancedSkill = "vue";
    }
    var senior = new SeniorCoder();
    senior.years++;
    // Equivalent to senior.years = senior.years + 1;
    console.log(senior.years);
    console.log(junior.years);
    // 4
    // 3

    As you can see, trying to change the years attribute through senior does not really affect junior's years attribute, but instead creates a new years attribute under senior and assigns it the result of adding junior.years to it

Object.creat()

  1. Object's create method is used to create an object, the parameter specifies a prototype, it can be an object or null

    var test = {
     name: "obj"
    }
    var obj = Object.create(test);
    console.log(obj.name);
    console.log(obj.__proto__ == test);
    // obj
    // true
  2. Object.creat(null)

    var obj = Object.create(null);
    console.log(obj);
    document.write(obj);
    // {}
    // Report errors

    The console shows that obj is an empty object with no attributes, including u proto_u, and errors will occur if you use document.write(obj), because the document.write method converts parameters to strings and prints them on the page. By default, the toString() method is called, and the toString method needs to be inherited from the prototype chain, while the obj methodIt is a completely empty object, has no prototype chain, and has no toString method, so it will fail

Prototype-based Inheritance

  1. Implement Inheritance Using Prototype Chain

    JuniorCoder.prototype.basicSkill = "html/css";
    function JuniorCoder() {
     this.lowerSkill = "javascript"
     this.age = 22;
    }
    var junior = new JuniorCoder();
    SeniorCoder.prototype = junior;
    function SeniorCoder() {
     this.advancedSkill = "vue";
    }
    var senior = new SeniorCoder();

    senior inherits junior's own properties and prototype chain

  2. call/apply implements inheritance

    function JuniorCoder(lowerSkill) {
     this.lowerSkill = lowerSkill;
    }
    function SeniorCoder(lowerSkill, advancedSkill) {
     JuniorCoder.apply(this, [lowerSkill]);
     this.advancedSkill = advancedSkill;
    }
    var senior = new SeniorCoder("javascript", "vue");

    Inherit the properties of the JuniorCoder instance itself, not the prototype chain

  3. Inheritance of Common Prototypes

    JuniorCoder.prototype.basicSkill = "html/css";
    function JuniorCoder() {
     this.lowerSkill = "javascript"
    }
    SeniorCoder.prototype = JuniorCoder.prototype;
    function SeniorCoder() {
     this.advancedSkill = "vue";
    }
    var senior = new SeniorCoder();

    senior inherits the prototype chain of the JuniorCoder instance and does not inherit its own properties, but changing SeniorCoder.prototype affects JuniorCoder.prototype

  4. Intermediate Object Inheritance (Grail Mode)

    JuniorCoder.prototype.basicSkill = "html/css";
    function JuniorCoder() {
     this.lowerSkill = "javascript"
    }
    Buffer.prototype = JuniorCoder.prototype;
    function Buffer() {}
    SeniorCoder.prototype = new Buffer();
    function SeniorCoder() {
     this.advancedSkill = "vue";
    }
    SeniorCoder.prototype.basicSkill = "markdown";
    console.log(SeniorCoder.prototype.basicSkill);
    console.log(JuniorCoder.prototype.basicSkill);
    // markdown
    // html/css

    It is more practical to inherit the prototype chain without inheriting its own properties and prototypes do not interact with each other

    After encapsulation, more suitable for enterprise development

    JuniorCoder.prototype.basicSkill = "html/css";
    
    function JuniorCoder() {
     this.lowerSkill = "javascript"
    }
    
    function SeniorCoder() {
     this.advancedSkill = "vue";
    }
    inherit(SeniorCoder, JuniorCoder);
    SeniorCoder.prototype.basicSkill = "markdown";
    console.log(new SeniorCoder());
    console.log(new JuniorCoder());
    
    function inherit(Target, Origin) {
     Target.prototype = Object.create(Origin.prototype);
     Target.prototype.constructor = Target;
     Target.prototype.superClass = Origin;
    }

    Create intermediate objects directly using Object's creat e method, set construtor, superClass attributes for easy analysis and maintenance

hasOwnProperty()

Determines if the property is the instance object itself, and returns true if it is

Car.prototype.brand = "BMW";
function Car() {
    this.color = "red";
}
var car = new Car();
console.log(car.hasOwnProperty("brand"));
console.log(car.hasOwnProperty("color"));
// false
// true

instanceOf

Determine if there is a construction method on the prototype chain of an instance object

JuniorCoder.prototype.basicSkill = "html/css";

function JuniorCoder() {
    this.lowerSkill = "javascript"
}

function SeniorCoder() {
    this.advancedSkill = "vue";
}
inherit(SeniorCoder, JuniorCoder);

function inherit(Target, Origin) {
    Target.prototype = Object.create(Origin.prototype);
    Target.prototype.constructor = Target;
    Target.prototype.superClass = Origin;
}

var senior = new SeniorCoder();

console.log(senior instanceof SeniorCoder);
console.log(senior instanceof JuniorCoder);
console.log(senior instanceof Object);
// true
// true
// true

Tags: Javascript Vue Attribute

Posted on Fri, 20 Mar 2020 23:52:48 -0400 by bache