The prototype

define

A prototype is a generic object that shares properties and methods for all instances of a particular type, so you can add this information directly to the prototype object without having to define object instance information in the constructor.

understand


In this example, we start with a Person variable of type function

  1. When this function is created, one is created for the function according to specific rulesprototypeProperty (pointer) pointing to a functionA prototype object.
  2. Add the Type and maxAge attributes directly to Person’sprototypeProperties of the
  3. We then create one using the new call constructor PersonInstance objectsP so that P can share properties and methods in the prototype object
  4. Inside this instance will be a pointer (internal property), called in ECMA-262 version 5[[Prototype]]. Although there is no standard way to access it in the script[[Prototype]], but Firefox, Safari, and Chrome all support one property per object__proto__Actually, it comes fromObject.prototype

Through comparison, the following conclusions can be drawn:


  • The Person () functionprototypeProperty and properties of the instance object P__proto__Properties refer to the prototype object (that isPrototype inheritanceEvery instance of the constructor has access to the constructor’s prototype! 🤯)
  • The prototype object is added by defaultconstructorThe attribute (also shared) refers back to the associated constructor Person
  • In the prototype object except containconstructorIn addition to attributes, other attributes are added later.

Note :length is the value of the attribute of the function object. It is the number of required parameters except the default parameter (such as function (xx = 0)). How do you create an object without a prototype? We can create a new Object using the object.create () method 💪🏼:

let obj = {};
let jbo = Object.create(null, {
  name: {
    writable: true./ / write
    enumerable: true./ / can be enumerated
 value: "yu"  } }); console.dir(jbo) // [Object: null prototype] { name: 'yu' } Copy the code

role

Take a simple chestnut 🌰

function Dog(name) {
  this.name = name;
  this.bark = function () {
    console.log('Woof! ');
  };
}  var dog1 = new Dog('jack'); var dog2 = new Dog('jane'); dog1.bark(); // Woof! dog1.bark(); // Woof! console.log(dog1.bark === dog2.bark); // false Copy the code

Bark events but same result returns false every time new creates a new function, consumption of memory, every time mentioned prototype will provide sharing for all instances of a certain type of attribute, so we can put this method on a prototype object, every time we need to use the time to call is ok:

function Dog(name) {
  this.name = name;
}
Dog.prototype.bark = function () {
  console.log('Woof! ');
};  var dog1 = new Dog('jack'); var dog2 = new Dog('jane'); dog1.bark(); // Woof! dog1.bark(); // Woof! console.log(dog1.bark === dog2.bark); // true Copy the code

The prototype in ES6

ES6 actually uses a simpler syntax for constructors and stereotypes: classes.

The chestnuts above 🌰 are spelled with es:

class Dog {
  constructor(name) {
    this.name = name;
  }
  bark() {
 console.log('Woof! ');  } }  var dog1 = new Dog('jack'); var dog2 = new Dog('jane'); dog1.bark(); // Woof! dog1.bark(); // Woof! console.log(dog1.bark === dog2.bark); // true Copy the code

They actually still work in the same way. Classes are just syntactic sugar for constructors!


summary

A prototype object is essentially an object, and it has attributes such as __proto__ and constructor, so a prototype object can access its prototype object via __proto__. You can also use constructor to know which instance object you belong to;

Prototype chain

define

Many OO languages support two types of inheritance: interface inheritance and implementation inheritance. Because functions do not have signatures, interface inheritance cannot be implemented in ECMAScript, only implementation inheritance is supported, and prototype chains are used as the primary way to implement inheritance. The basic idea is to use stereotypes to make one reference type inherit the properties and methods of another.

For example 🌰: When we access the name attribute, the engine first looks for a definition in dog1, returns the attribute if found, otherwise the engine will continue to search for the attribute in the prototype via the __proto__ attribute

If not, the currently obtained prototype object is treated as an instance object and continues to look through its __proto__ property, tracing back until __proto__ is null at the end of the prototype chain. A chain of interconnected prototypes is called a prototype chain

Note: When you add a property to an object instance, the property masks the property of the same name that is stored in the prototype object. You can access the prototype property again by deleting the instance property

function Dog() {}
Dog.prototype.name = 'jack';
var dog1 = new Dog();
dog1.name = 'jane';
console.log(dog1.name); // Jane -- from an instance
delete dog1.name; console.log(dog1.name); // Jack -- from the prototype Copy the code

implementation

The basic idea of a stereotype chain is to make the stereotype equal to an instance of another type, in which case the stereotype will contain a pointer to another stereotype, which in turn will contain a pointer to another constructor. Another prototype is an instance of another type, and so on, forming a chain of instances and prototypes. This is the basic concept of the so-called prototype chain.

Give an example.

function Animal() {
  this.type = 'animal';
}
Animal.prototype.getType = function () {
  return this.type;
};  function Dog() {  this.name = 'dog'; } Dog.prototype = new Animal();  Dog.prototype.bark = function () {  console.log('Woof! '); };  var dog1 = new Dog(); dog1.getType(); // animal dog1.__proto__ === Dog.prototype; // true Dog.prototype.__proto__ === Animal.prototype; // true Animal.prototype.__proto__ === Object.prototype; // true Object.prototype.__proto__ === null; // true  Copy the code

In this 🌰, Dog inherits Animal by creating an instance of Animal and assigning it to dog.prototype

At this point, Dog. Prototype can obtain the attributes and methods in the original Animal instance, and can also add a new method bark to its prototype.

Dog1 points to the Dog prototype, and the Dog prototype points to the Animal prototype.

In animal.prototype, dog. prototype is now an instance of Animal, so the instance property type is in that instance (dog.prototype). Also, note that dog1. Constructor now points to Animal

Calling dog1.getType() goes through three search steps:

  1. Search instance;
  2. Search Dog. The prototype;
  3. Search Animal. The prototype

The method is found in the last step. In the absence of a property or method, the search process always stops by going round and round to the end of the prototype chain.

Note: The source of all our built-in methods is on the prototype chain! 😃 : for example, toString() and valueOf(). We know that all reference types inherit from Object by default, and this inheritance is also implemented through the stereotype chain. The default prototype for all functions is an instance of Object, so the default prototype contains an internal pointer to Object.prototype. 🙌 🏼

Graphic summary:


In a word, Dog inherited from Animal, and Animal inherited from Object. When instance.tostring () is called, you are actually calling the method stored in Object.prototype.

Note: Prototypical inheritance means copying operations, whereas JavaScript does not copy object properties by default. Instead, JavaScript simply creates an association between two objects. Causes instances of subclasses to share the reference attributes of the parent class constructor, as shown below:

Funcion and Object

The prototype object also has a __proto__ attribute, traceable up to null.

var Dog = function () {};
var dog = new Dog();

console.log(dog instanceof Dog); //=> true
console.log(dog instanceof Object); //=> true
console.log(dog instanceof Function); //=> false  console.log(dog.__proto__ === Dog.prototype); //=> true console.log(dog.__proto__.constructor === Dog); //=> true  console.log(Dog.__proto__ === Function.prototype); //=> true console.log(Dog.__proto__.constructor === Function); //=> true  console.log(Function.__proto__ === Function.prototype); //=> true console.log(Dog.__proto__ === Dog.prototype); //=> false console.log(Dog.__proto__ === Function.prototype); //=> true  console.log(Function.__proto__.constructor === Function); //=> true console.log(Function.__proto__.__proto__); / / = > {} console.log(Function.__proto__.__proto__ === dog.__proto__.__proto__); //=> true console.log(dog.__proto__.__proto__.__proto__ === null); //=> true  console.log(dog.__proto__ === Dog.prototype); //=> true console.log(dog.__proto__.__proto__ === Object.prototype); //=> true console.log(dog.__proto__.__proto__ === Function); //=> false Copy the code

summary


  1. All functions are created by the Function Function itself, so “function. prototype === Dog”.__proto__Function. Prototype === Function.__proto__
  2. All function prototype objects are created by the Object function, so “object. prototype === dog.prototype.__proto__
  3. Object is also a function. Function. Prototype === Object__proto__“;
  4. Function. Prototype is an ordinary Object created by Object, so “Function. Prototype”.__proto__= = = Object. The prototype”

Relevant methods

  • IsPrototypeOf: indicates whether the call object on another object of the prototype chain: Animal. Prototype. IsPrototypeOf (dog1)

  • HasOwnProperty: Checks whether a property exists in an instance or prototype, returns true: dog1.hasownProperty (‘name’)

  • Instanceof: Constructor that tests whether an instance’s prototype chain has been present :dog1 instanceof Animal

  • GetPrototypeOf: Get [[prototype]] : Object.getProtoTypeof (dog1) == dog.prototype

  • The in operator returns true as long as the property is accessible through the object :”name” in dog1

    All of the above examples return true

Since the in operator returns true whenever the property is accessible through the object, hasOwnProperty() returns true only if the property exists in the instance, so hasOwnProperty() returns false whenever the in operator returns true, You can determine that the property is the property in the stereotype.

‘name’ in dog1 && ! dog1.hasOwnProperty(‘name’); // false

‘bark’ in dog1 && ! dog1.hasOwnProperty(‘bark’); // true

Refer to the article 📜

❤️ javaScript Advanced Programming (3rd edition)

❤️ Understanding of prototype, prototype chain, Function and Object

❤️ Graphic Javascript prototype chain

Extension 🏆

If you find this article helpful, check out my other articles at ❤️ :

👍 10 simple tips to make your vue.js code more elegant 🍊

👍 Close contact with websocket🚀

👍 5 Design patterns to know for Web development

👍 Data structures Web development should know about