Prototype chain

To understand a prototype chain, what is a prototype

First, prototype mode

Each function we create has a ==prototype== (prototype) property, which points to the prototype object. Instance objects created through this function share all properties and methods on the prototype object.

function Person(){
    
}

Person.prototype.name = 'test';
Person.prototype.age = 25;
Person.prototype.sayName = function(){
    console.log(this.name);
}

const person1 = new Person();
person1.sayName(); //'test'

const person2 = new Person();
person2.sayName(); //'test'

console.log(person1.sayName === person2.sayName); //true
Copy the code

Second, prototype object

  1. Understanding prototype objects

Whenever a function is created, a ==prototype== attribute (pointing to the function’s prototype object) is generated for that function. By default, the prototype object automatically gets a ==constructor== property that contains a pointer to the function of the Prototype property. When this function is called to create an instance, the instance contains a pointer [[Prototype]] (internal property) to the constructor’s Prototype object. While there is no standard way to access [[Prototype]] in scripts, Firefox, Safari, and Chrome all support a __proto__ attribute on each object. In other implementations, this property is completely invisible to the script.

Although [[Prototype]] is not accessible in any implementation, it is possible to determine whether this relationship exists between objects using the ==isPrototypeOf== method. This method returns true if [[Prototype]] refers to the object (Person.prototype) on which isPrototypeOf() is called.

Person.prototype.isPrototypeOf(person1); //true
Person.prototype.isPrototypeOf(person2); //true
Copy the code

The == object.getProtoTypeof == method can return the value of [[Prototype]]. Such as:

Object.getPrototypeOf(person1) === Person.prototype // true
Object.getPrototypeOf(person1).name // "test"
Copy the code

Whenever an attribute of an object is read, the search begins with the object instance itself, and if it does not, the search continues for attributes in the prototype object. Although you can access values stored in the stereotype through the object instance, you cannot override values in the stereotype through the object instance.

person1.name = "Greg";
console.log(person1.name); // "Greg"From the instance itself console.log(person2.name); //"test"From the prototype objectCopy the code

The ==hasOwnProperty== method checks whether an attribute exists in an instance or in a stereotype (inherited from Object) and returns true only if the given attribute exists in an Object instance.

person1.hasOwnProperty("name"); //true
person2.hasOwnProperty("name"); //false

delete person1.name;

person1.hasOwnProperty("name"); //false
Copy the code
  1. Stereotype and in operator

When used alone, the IN operator returns true whenever the given property is accessible, whether it exists in an instance or in a stereotype.

person1.hasOwnProperty('name'); //false
'name' in person1; //true

person2.hasOwnProperty('name'); //false
'name' in person2; //true

person1.name = 'ohyes';
person1.name; // 'ohyes'
person1.hasOwnProperty('name'); //true
'name' in person1; //true
Copy the code
// By using the hasOwnProperty methodinThe operator determines whether a property exists in an instance or stereotypefunction hasPrototypeProperty(obj,name){
    return! obj.hasOwnProperty(name) && nameinobj; } // Attribute exists in the instance, returnfalse; Exists in the prototype returnstrue
Copy the code

A for-in loop that returns all enumerable properties of an object, whether they exist in an instance or stereotype. Instance attributes that mask non-enumerable attributes in stereotypes can also be returned in for-in loops. However, there is a bug in IE8 and earlier that instance properties that mask non-enumerable properties do not appear in for-in loops.

To get all enumerable instance properties on an Object, use the object.keys () method.

Object.keys(Person.prototype); / / /"name"."age"."sayName"] Object.keys(person1); / / /"name"]
Copy the code

If you want to get all the instance attributes, whether or not can be enumerated, can use the Object. The getOwnPropertyNames () method

Object.getOwnPropertyNames(Person.prototype); / / /"constructor"."name"."age"."sayName"]
Copy the code
  1. Problems with prototype objects

All attributes in the stereotype are shared by many instances. There are particular problems with stereotype objects that contain attributes that reference type values.

Person.prototype.friends = [person.prototype. friends = [person.prototype. friends = [person.prototype. friends = ['one'.'two'];
person1.friends.push('three'); person1.friends; / / /"one"."two"."three"] person2.friends; / / /"one"."two"."three"]
person2.friends === person1.friends; // true
Copy the code

Prototype chain

The prototype chain is the main method to implement inheritance. The basic idea is to use stereotypes to make one reference type inherit the properties and methods of another. Each constructor has a Prototype property that points to the prototype object. Each prototype object contains a constructor pointer. Change the constructor’s prototype property to an instance of another constructor, at which point the prototype object will contain a pointer to another prototype. If another prototype is an instance of another type, then the above relationship still holds, and so on, the chain of instance and prototype is formed. That’s the concept of a prototype chain.

// Modify the constructor's prototype property to point to another constructor instance to implement inheritancefunction SuperType(){
    this.property = true;    
}

SuperType.prototype.getSuperValue = function() {return this.property;
}

function SubType(){
    this.subproperty = false;
}

SubType.prototype = new SuperType();

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

let instance = new SubType();
console.log(instance.getSuperValue()); //true
Copy the code