JavaScript inheritance-detailed explanation of prototype chain inheritance

table of Contents

1. Review the prototype concept:

Second, the prototype chain inheritance

3. Points to note:

Four: The problem of the prototype chain:


1. Review the prototype concept:

Before learning prototype chain inheritance, let's briefly review the concept of prototype :

Each function has a prototype attribute, which by default points to an empty Object object (called the prototype object), and there is a constructor attribute in the prototype object, which points to the function object.

function foo(){
    
}
console.log(foo.prototype.constructor == foo); //true

The relationship between constructor, prototype, and instance:

Each constructor has a prototype object (Foo.prototype), the prototype object contains a pointer to the constructor (constructor), and the instance contains an internal pointer (_proto_) to the prototype object.

function Foo(){
    this.name="小白";
}
var foo = new Foo();
console.log(foo.name);

console.log(Foo.prototype.constructor === Foo);
console.log(foo.__proto__ === Foo.prototype);


 Second, the prototype chain inheritance

//    创建SuperType函数   并添加property属性
    function SuperType() {
        this.property = true;
    }

//    给其原型上添加一个方法 getSuperValue
    SuperType.prototype.getSuperValue = function () {
        return this.property;
    };

//    创建一个SubType函数 并添加subproperty属性
    function SubType(){
        this.subproperty = false;
    }

//    继承SuperType(重点)
    SubType.prototype = new SuperType();

    SubType.prototype.getSubValue = function () {
        return this.subproperty;
    };

    var instance = new SubType();
    alert(instance.getSuperValue());

Explanation: The above code defines two types: SuperType and SubType. Each type has an attribute and a method. The main difference between them is that SubType inherits SuperType, and inheritance is achieved by creating an instance of SuperType and assigning the instance to SubType.prototype. The essence of the realization is to rewrite the prototype object and use the prototype object of SubType as an instance of SuperType . Then all the properties and methods that originally existed in the SuperType instance now also exist in SubType.prototype. After establishing the inheritance relationship, we added a method to SubType.prototype, thus adding a new method on the basis of inheriting the properties and methods of SuperType.

 In the above code, we did not use the prototype provided by SubType by default, but replaced it with a new prototype, and this prototype is an instance of SuperType . So the new prototype not only has all the properties and methods owned by an instance of SuperType, but also has a pointer inside it that points to the prototype of SuperType.

    console.log(SubType.prototype.__proto__ === SuperType.prototype); //true

The end result is that instance points to the prototype of SubType, and the prototype of SubType points to the prototype of SuperType.

3. Points to note:

1. Don't forget the default prototype:

The explicit prototypes of all functions point to an empty Object object except for Object, so the default prototype will contain an internal pointer to Object.prototype. This is the fundamental reason why all custom types inherit default methods such as toString() and valueOf(). 

2. Prudent definition method:

Sometimes a subtype needs to renew a method in the supertype, or need to add a method that does not exist in the supertype. The code to add a method to the prototype must be placed after the statement that replaces the prototype .

    function SuperType() {
        this.property = true;
    }
    SuperType.prototype.getSuperValue = function () {
        return this.property;
    };
    function SubType(){
        this.subproperty = false;
    }
//    继承SuperType
    SubType.prototype = new SuperType();
//添加新方法
    SubType.prototype.getSubValue = function () {
        return this.subproperty;
    };
//重新超类中的方法
    SubType.prototype.getSuperValue = function () {
        return false;
    };
    
    var instance = new SubType();
    alert(instance.getSuperValue());

3. When implementing inheritance through the prototype chain, you cannot use object literals to create prototype methods. Because it will rewrite the prototype chain

    function SuperType() {
        this.property = true;
    }
    SuperType.prototype.getSuperValue = function () {
        return this.property;
    };
    function SubType(){
        this.subproperty = false;
    }
//    继承SuperType
    SubType.prototype = new SuperType();
//使用对象字面量添加新方法
    SubType.prototype = {
        getSubValue : function(){
            return this.subproperty;
        },
        someOtherMethod : function(){
            return false;
        }
    };
    var instance = new SubType();
    alert(instance.getSuperValue());

Four: The problem of the prototype chain:

1. Prototype properties containing reference type values ​​will be shared by all instances, which is why properties are defined in the constructor instead of the prototype object.

    function SuperType(){
        this.colors = ["red","blue","green"];
    }
    function SubType() {

    }
//    继承了SuperType
    SubType.prototype = new SuperType();

    var instance = new SubType();
    instance.colors.push("black");
    alert(instance.colors);

    var instance2 = new SubType();
    alert(instance2.colors);

In this example, the SuperType constructor defines a colors property, which contains an array (reference data type). Each instance of SuperType will have the colors attribute. When SubType inherits SuperType through the prototype chain, it also has a colors property. The point is that SubType will share this property, so we see that after the value of the array colors is modified in the instance instance, the colors value in instance2 has also changed.

2. When creating an instance of a subtype, you cannot pass parameters to the supertype's constructor.

 

Note: For information, refer to "JavaScript Advanced Programming"

Guess you like

Origin blog.csdn.net/weixin_43690348/article/details/112965496