We understand the inheritance of prototype through [[prototype]], proto and Prototype.

[[prototype]]

The ECMAScript standard states that every object has a built-in attribute [[prototype]] that points to an object’s prototype object. When looking for an object’s property or method, if it is not found on the current object, it looks on its prototype object, if not on the prototype object, it looks on the prototype object of the prototype object, and so on until the prototype object of an object is NULL (null has no prototype). As you can see, this kind of layer up lookup is a chain lookup. At each layer, the object has a link to its prototype object ([[prototype]]). The whole chain made up of these links is called the prototype chain.

As shown in Figure 1, the idea of prototype chain search is roughly as follows:

  • When object1 looks for an attribute, it first looks for the attribute it owns. If not, it looks for the attribute in object1__proto__([[prototype]]) at this time__proto__Pointing to the object2.
  • If the object object2 does not have an attribute to look for, the__proto__If not, continue to look up.
  • Up to the prototype of the Object Object__proto__If the value is null, no search is performed.



Builts-in is used to build built-in functions such as toString(), valueOf, etc.

__proto__

[[Prototype]] is a built-in attribute. We can’t get it directly. Many browsers implement object.prototype.__proto__. __proto__ and [[Prototype]] are essentially the same thing, both pointing to an object’s Prototype object. On the other hand, setting [[Prototype]] is a slow operation that affects performance, so using __proto__ is debatable, and using Object.getProtoTypeof and Object.setProtoTypeof is more recommended for accessing Prototype objects (however, If performance is an issue, avoid it).

prototype

Prototype is a property of constructors (an object with [[Construct]] inner methods), such as functions (non-arrow functions). Instance objects do not have this property. The prototype object is considered a normal object inside the constructor (or pointing to a normal object), but is unfortunately called prototype. When the constructor executes, Constructor prototype is automatically assigned to __proto__(if no object is returned inside the constructor) so that constructor prototype and properties on the prototype chain can be shared on the new instance. Prototype is a completely different concept from __proto__ and [[prototype]], and the common confusion comes from using the term prototype object to refer to different objects.

Animal gets access to the prototype property food and eat from the object instantiated by new.

var Animal = function(name) {
  this.name = name;
};
Animal.prototype.food = 'meat';
Animal.prototype.eat = function() {
  console.log(this.name + ' eat ' + this.food);
};
var panda = new Animal('panda');
var dog = new Animal('dog');
console.log(panda.eat()); // panda eat meat
console.log(dog.eat()); // dog eat meat
console.log(panda.__proto__=== Animal.prototype); // true
Copy the code

As shown in the following figure, panda and dog can access the food and eat attributes on the Animal prototype because Animal’s prototype object is assigned its __proto__ property when the constructor is called. If the instance object does not find its own method (panda.eat), it will look in the __proto__ object, and this object happens to be the Animal prototype object, it has eat method, so it can successfully access eat method.

Uncaught TypeError: / / Fish prototype = Animal; / / Fish prototype = Animal; Nimo.eat is not a function. This error occurs because we mistake __proto__ as a prototype object. We have already seen that inheritance is implemented through a chain of archetypes, which in turn is concatenated by __proto__. When Fish’s prototype is set to Animal, nimo’s __proto__ is Animal. Eat = Animal Animal __proto__ (eat) ¶ Animal __proto__ (eat) ¶ Animal __proto__ (eat) ¶

var Animal = function(name) {
  this.name = name;
};
Animal.prototype.food = 'meat';
Animal.prototype.eat = function() {
  console.log('I can eat' + this.food);
};

var Fish = function(name) {
  this.name = name;
};
Fish.prototype = Animal;

var nimo = new Fish('nimo');
console.log(nimo.eat()); // Uncaught TypeError: nimo.eat is not a function
Copy the code

Create objects and prototype chains in different ways

  • Syntax structure creates objects

    • Object literals

      Object literals create objects whose prototype chain is obj –> object. prototype –> null

      var obj = { a: 1 };
      Copy the code
    • Array literals

      Prototype –> Object. Prototype –> null

      var arr = [1, 2];
      Copy the code
    • Function literal

      Prototype –> Object. Prototype –> null

      function f(){ console.log('func'); }Copy the code
  • The constructor creates objects

    Prototype –> Object. Prototype –> null

    var Animal = function(name) { this.name = name; }; Animal.prototype.food = 'meat'; Animal.prototype.eat = function() { console.log('I can eat' + this.food); }; Prototype var panda = new Animal('panda');Copy the code
  • Object.create Creates an Object

    In ES5, a new method was introduced to create objects, object.create, where the prototype of the new Object is the first argument passed in.

      var a = { x: 1 };
      // a --> Object.prototype --> null
    
      var b = Object.create(a);
      // b --> a --> Object.prototype --> null
      console.log(b.__proto__ === a); // true
      console.log(b.x); // 1
    
      var c = Object.create(b);
      // c --> b --> a --> Object.prototype --> null
      console.log(c.__proto__ === b); // true
    Copy the code

conclusion

  • Any object can be a prototype object for another object (__proto__Object to point to).
  • [[Prototype]]A built-in property that points to the prototype object for an object and cannot be accessed directly.
  • __proto__A property that is implemented for a non-standard, but only for easy access to the prototype object, and[[Prototype]]They’re essentially the same as pointing to the prototype object, and they’re properties that all objects have.
  • The prototype for a[[construct]]The property of the object of the inner method, which is itself just a normal object, just happens to be called a prototype object, and its purpose is to assign the so-called prototype object to the instance when the constructor generates a new instance__proto__Property so that new instances can pass through__proto__To inherit the methods in the constructor prototype. You can see prototype and__proto__The prototype object referred to is a completely different concept.
  • The instance object has no Prototype property,