JavaScript is dynamic and does not itself provide a class implementation. (The class keyword was introduced in ES2015/ES6, but that’s just syntactic sugar and JavaScript is still prototype-based).

Only object types have the concepts of inheritance and stereotypes

Together, the prototypes that are traced upward form the prototype chain

  • Each instance object has a private attribute (called __proto__) that points to its constructor’s prototype.
  • The prototype object also has a prototype object of its own (__proto__), layer up until the prototype object of an object isnull.
  • By definition,nullNo prototype, and as thisPrototype chainThe last link in the.
  • Almost all objects in JavaScript are instances of Object at the top of the prototype chain.

The above explanation may be a little convoluted, but the following should make it a little clearer.

Inheritance based on prototype chain

Inherit the attributes

JavaScript objects are dynamic property “packages” (referring to their own properties). JavaScript objects have a chain that points to a prototype object. When it tries to access an object’s properties, it searches not only for that object, but also for that object’s prototype, and the prototype of that object’s prototype, working its way up until it finds an attribute with a matching name or reaches the end of the prototype chain.

Here’s what happens when you try to access a property:

// Create an object o from a constructor that has attributes A and b:
let f = function () {
   this.a = 1;
   this.b = 2;
}
Function f() {this.a = 1; this.b = 2; } * /

let o = new f(); // {a: 1, b: 2}

console.log(o) // f { a: 1, b: 2 }

// point to the constructor
console.log(o.constructor) 
// function () {
// this.a = 1;
// this.b = 2;
// } 

// The instance has no prototype object
console.log(o.prototype) // undefined

// The prototype object of the constructor
console.log(o.constructor.prototype, f.prototype)  f {} f {}

// The instance's __proto__ points to the constructor's prototype object
console.log('o.proto', o.__proto__, typeof o.__proto__) // f {} object


Copy the code

To sum up, the whole prototype chain is as follows:

Now, the next four lines are clear

  • Each instance object has a private attribute (called __proto__) that points to its constructor’s prototype.
  • The prototype object also has a prototype object of its own (__proto__), layer up until the prototype object of an object isnull.
  • By definition,nullNo prototype, and as thisPrototype chainThe last link in the.
  • Together, the prototypes that are traced upward form the prototype chain
  • The prototype of the object is__proto__attribute
  • The function has two attributes, one of which is__proto__And there’s one that’s function specificprototypeProperty, because functions have a dual identity, that is, they can be instances or constructors
  • Object.prototype{}
  • The arrow Function is a Function created by Function, but it has no prototype property and no constructor property, so it has no constructor and cannot be used as a constructor

Let’s make some changes to the constructor prototype

// Define attributes on the prototype of f functions
f.prototype.b = 3;
f.prototype.c = 4;
Copy the code

Do not define objects directly on the prototype of f functions, f. protoType = {b:3,c:4}; This directly breaks the prototype chain

// The instance's __proto__ points to the constructor's prototype object
console.log('o.proto', o.__proto__) // f { b: 3, c: 4 }
Copy the code

The prototype chain after the changes is as follows:

// Following the ECMAScript standard, the someObject.[[Prototype]] symbol is used to refer to the Prototype of someObject.

console.log(o.a); / / 1
// Is a a property of o? Yes, this property has a value of 1

console.log(o.b); / / 2
// is b a property of o? Yes, this property has a value of 2
// The prototype also has a 'b' attribute, but it will not be accessed.
// This condition is called "property shadowing"

console.log(o.c); / / 4
// Is c a property of o? No, let's see if it's on the prototype
[[Prototype]] // c is an attribute of o.[[Prototype]]. Yes, this property has a value of 4

console.log(o.d); // undefined
// is d a property of o? No, let's see if it's on the prototype
[[Prototype]] // d is an attribute of o.[[Prototype]]. No, let's see if it's on the prototype
// o.[[Prototype]].[[Prototype]] is null
// Find d attribute, return undefined
Copy the code

Inherited methods

JavaScript does not have the “methods” defined in other class-based languages. In JavaScript, any function can be added to an object as an object property. Function inheritance is no different from any other attribute inheritance, including the above “attribute masking” (which is equivalent to method overwriting in other languages).

When an inherited function is called, this refers to the currently inherited object, not the inherited function’s prototype object.

ECMAScript 5 introduced a new method: Object.create(). You can call this method to create a new object. The prototype of the new object is the first argument passed when the create method is called:

var o = {
  a: 2.m: function(){
    return this.a + 1; }};console.log(o.m()); / / 3
When o.m is called, 'this' refers to o.

var p = Object.create(o);
// p is an object inherited from o

p.a = 4; // create p's own attribute 'a'
console.log(p.m()); / / 5
// when p.m is called, 'this' points to p
// P inherits o's m function
// 'this.a' = 'a' = 'a'
Copy the code

Related series: Front End Foundation from scratch journey (super detailed, constantly updated ~)

If you learn something new, please give the author a thumbs up

Reference Documents:

MDN: Inheritance and prototype chain