Prototype, prototype chain

Before we get started, you should understand two definitions, a prototype and a prototype chain:

Prototype: By default, all functions have a public, non-enumerable property called Prototype that points to another object, the prototype of the function

The prototype chain: Each prototype Object has a pointer __proto__, which points to the prototype Object at the next level, and the structure of the prototype Object at the next level is still similar, looking up until object.prototype. __ Proto__ =null indicates reaching the top of the prototype chain. The whole process is called prototype chain.

Think of it as a ladder, joined together by __proto__. Object properties and methods are searched all the way up to the top of the ladder. In fact, everything in JS is an object, not Java class language, there is no copy mechanism, the connection between objects can only be linked through the prototype chain.

Prototype and __ proto__

As you can see from the code below, the Person function has a Prototype property, and printing this property on the console returns an object that is what we call a prototype. New implements an object named Person. Person has a property called __proto__, which points to the object’s prototype.

function Person() {} var person = new Person() console.log(person.__proto__ === Person.prototype) console.log(Person ===  Person.prototype.constructor)Copy the code
  • Each object has a __ proto__ attribute that points to its Prototype object
  • Each constructor has a Prototype property, and the constructor in the Prototype object points to the constructor itself
  • The __proto__ of the instance object points to the prototype object

The prototype chain:

var obj = { a: 2}
var myObj = Object.create(obj)
myObj.a // 2
Copy the code

If the desired attribute cannot be found in the object itself, the prototype chain of the object is continued. MyObj does not have an A attribute, so the a attribute on obj is found through the prototype chain. If no A is found in obj and the prototype chain is not empty, the search will continue until the top of the prototype chain is not found and undefined will be returned. (Use the in operator to check if the property is present in the object, and also look up the entire prototype chain of the object.)

Prototype chain: Each prototype object has a pointer __proto__, which points to the prototype object at the next level, and the structure of the prototype object at the next level is still similar. When object.prototype. __ proto__ is null, the top of the prototype chain is reached.

Var arr = [1,2,3] arr.valueof ()Copy the code

The prototype chain is as follows:

arr —> Array.prototype —> Object.prototype —> null

This is the legendary chain of archetypes, looking up one layer at a time, and finally returning undefined

Extension: All normal prototype chains end up pointing to the built-in Object.prototype, which contains. ToString,. ValueOf, and many other common functions, so ordinary objects can use these methods directly.

Property setting and masking

Setting a property for an object is not just about adding a new property or changing an existing property value.

var obj1 = { a: 1} var myObj = object.create (obj1) console.log(obj1.hasownProperty ("a")) // true hasOwnProperty: To determine if a property is on an object, Console. log(myobj.hasownProperty ("a")) // false myobj.a ++ console.log(obj1, myObj) console.log(myObj.hasOwnProperty("a")) // trueCopy the code
  • 1. If an obj object contains a common data access attribute named foo, this assignment statement only modifies the value of the existing attribute

  • 2. If obj does not have a foo attribute, the prototype chain is searched, and if the prototype chain does not find foo, foo is added directly to obj

  • 3. If foo is not on obj and appears in the stereotype chain, and foo is not marked read-only, a new property named foo is added to obj. This property is masked

  • 4. If foo appears in both obJ and obJ’s stereotype chain, the attributes contained in obj mask all foo attributes from the stereotype chain and add a new attribute directly to the object

Object associated

Object.create(…) : creates a new object and associates it with the specified object, taking full advantage of the prototype chain mechanism and avoiding unnecessary trouble (such as constructor calls using new that generate.prototype and.constructor).

Object.create() = function(o) {
	function F() {}
    F.prototype = o
    return new F()
}
Copy the code

New (): an empty object that points to the constructor’s prototype and is returned after the constructor is executed. If you don’t want the properties and methods of the parent class, add new to function prototype.

inheritance

Inheritance is when one object directly uses the properties and methods of another object

In JavaScript, there is no replication mechanism, and you can’t create multiple instances of a class. You can only create multiple objects, and then create an association between them, so that one object can access the properties and methods of another object through delegation. This mechanism is called stereotype chain inheritance, which is more accurately described as delegation

Function Animal(name) {this.name = name this.sleep = function() {console.log(this.name + 'I am sleeping! ')}} Animal. Prototype. Eat = function(food) {console.log(this.name + 'eating' + food)}Copy the code

1. Prototype chain inheritance

function Cat() {}
Cat.prototype = new Animal('cat')

var cat = new Cat()
console.log(cat.name)
console.log(cat.eat('fish'))
console.log(cat.sleep())
Copy the code

Important: Make the prototype of the new instance equal to the instance of the parent class. Features: Based on the prototype chain, inherit the attributes and methods of the parent class instance, but also inherit the attributes and methods of the prototype. Disadvantages: Can’t implement multiple inheritance. All new instances share the attributes of the parent instance. (Attributes on the stereotype are shared; if one instance modifies the stereotype attributes, the other instance’s stereotype attributes are also modified!)

2. Structural inheritance

function Dog() { Animal.call(this, 'Tom ')} var dog = new dog () console.log(dog.name) console.log(dog.sleep()) // console.log(dog.eat('bone')) // errorCopy the code

Important: Use.call() and.apply() to introduce the superclass constructor into the subclass function, self-executing features: can achieve multiple inheritance. Arguments can be passed to the parent in a child instance. Disadvantages: Can only inherit the attributes and methods of the parent instance, not the attributes and methods of the prototype. Every time you use it, you have to call it again.

3. Combinatorial inheritance

function Snake() {
  Animal.call(this, 'snake')
}
Snake.prototype = new Animal()

var snake = new Snake()
console.log(snake.name)
console.log(snake.sleep())
console.log(snake.eat('apple'))
Copy the code

Key points: combination of construction inheritance and prototype chain inheritance. By calling the superclass constructor, you inherit the attributes of the parent class and retain the advantages of passing parameters. Then, by using the parent class instance as the subclass prototype, you realize the disadvantage of function reuse: if you call the parent constructor twice (memory consuming), the subclass constructor will replace the parent constructor on the prototype.

4. Inheritance of the original type

Function content(obj) {function F(){} f.totype = obj return new F()} var Irabbit = new Animal('rabbit' var rabbit = content(Irabbit) console.log(rabbit.name) console.log(rabbit.sleep()) console.log(rabbit.eat('turnip'))Copy the code

Important: Wrapping an object with a function and then returning a call to that function makes that function an instance or object that can be added with any properties it wants. Object.create () works this way. Features: Similar to copying an object, wrapped in a function. Disadvantages: All instances inherit properties from the stereotype. Reuse cannot be achieved. (New instance attributes are added later)

5, parasitic, parasitic combination inheritance (common)

Parasitism: returns an object within a function and calls the combination: 1. The prototype of the function is equal to another instance. 2. Use apply or call to introduce another constructor that takes arguments

Function Pig() {Animal. Call (this, 1) {Animal. 'pig') // inherits the parent constructor property} // Resolves the problem of class combinatorial double calls to the constructor property. Constructor = new Pig() console.log(pig.name) console.log(pig.sleep()) console.log(pig.eat('rice'))Copy the code

Fixed an issue with combination inheritance

6, copy inheritance, instance inheritance (remember the name, ignore)

conclusion

If you want to access a property that doesn’t exist in the object, the [[Get]] operation looks for the object associated with the stereotype inside the object. This association actually defines a chain of stereotypes that are iterated over when looking for properties and methods.

All normal objects have a built-in object. prototype that points to the top of the prototype chain and stops if the specified property is not found in the chain. ToSting (), valueOf(), and other generic functions exist on the Object.prototype Object, so all objects can use them

Inheritance can be divided into seven types, but it is important to master five of the above examples.