Fully understand the prototype, prototype chain
Prototype and inheritance are two very important concepts in JS. A thorough understanding of the prototype is also the premise of learning inheritance well. This article will take a comprehensive look at prototypes and prototype chains from three aspects: common objects, reference objects, and built-in objects.
Common object archetypes:
We all know that when accessing properties and methods on an object instance, we first look in the instance itself. If not, it looks for the instance object’s implicit __proto__ attribute, which is the prototype object of the instance’s constructor. If not, access to the prototype Object’s prototype continues until object.prototype.__proto__ (null).
This is why all objects contain the toString method, because toString is the method above Object.prototype. All objects along the prototype chain will eventually find Object.Prototype.
function Person(name) { this.name = name } Person.prototype.getName = function() { console.log(this.name) } let person = New Person('Jack') // Finds the name attribute directly on the instance. Person.getname () // Console.log (person.name) did not find getName on the instance itself, person.__proto__ found getName on the instance itself __proto__ (Object. Prototype) finds toString method console.log(person.tostring ())Copy the code
The chain along which __proto__ looks up attributes is what we call the prototype chain. So how does an instance access a method on a constructor prototype object in JS? How are instances traced up the prototype chain by __proto__?
We know that in JS:
- Every function exists
prototype
Property that points to the prototype object of the function. Constructor instantiation can be used to create an object in js. The constructor containsprototype
Property that points to the constructor’s prototype object. - Every object exists
__proto__
Property to describe the prototype of the object. And the object’s prototype points to the constructor that instantiates the objectprototype
“, that is,instance.__proto__ === construction.prototype
. - The prototype object of a function is also an object, the prototype object of all functions
__proto__
Will pointObject.prototype
The picture above says:
The constructor’s prototype object has a constructor property that points to the constructor itself.
Console printing:
console.log(person.__proto__)
console.log(Person.prototype)
console.log(person.__proto__ === Person.prototype)
console.log(Person.prototype.constructor === Person)
Copy the code
The prototype of a reference type object:
In the example above, we looked at the prototype chain for common objects and constructors. In JS, everything is an object, and a reference type value (array, object, function) is also an object. If an object is an object, it has a __proto__ attribute that points to the object’s prototype, corresponding to the constructor’s prototype object.
The constructors corresponding to Array, Object, Function and other reference types are the built-in js functions Array, Object, and Function. You can use these constructors to create values of reference types. However, in normal development, we are used to declaring an array or object in a literal manner. But no matter how you create a reference type, their prototype chain is the same.
Let arr = new Array(1,2,3) let obj = new Object({name: 'Jack'}) let fn = new Function('a', 'b', 'return a + b'); alert(fn(1, 2) ); / / 3Copy the code
The __proto__ attribute of a normal object refers to the prototype of its constructor.
console.log(arr.__proto__ === Array.prototype) //true
console.log(obj.__proto__ === Object.prototype) //true
console.log(fn.__proto__ === Function.prototype) //true
Copy the code
That’s why all functions have call, apply, and bind methods. Since these methods are on function. prototype, the Function calls call, which does not find a method by itself, along the prototype chain, calls fn.__proto__, which finds the call method.
Function.prototype.hasOwnProperty('call') // true
Copy the code
The prototype of the built-in function object:
We know the relationship between their stereotypes and some of the built-in constructors from the values of reference types such as arrays and objects.
The built-in functions Object, Function, Number, String, Array, and Boolean are all functions and also objects. Where does their __proto__ point to?
As we know, normal functions can be created with new Function(), so __proto__ of normal functions points to function.prototype. The built-in functions are also Function objects created from new Function(), and their __proto__ points to function.prototype.
// True console.log(object.__proto__ === function.prototype) console.log(array.__proto__ === function.prototype) console.log(Number.__proto__ === Function.prototype) console.log(String.__proto__ === Function.prototype) console.log(Boolean.__proto__ === Function.prototype) console.log(Date.__proto__ === Function.prototype)Copy the code
For both normal functions and built-in constructors, their __proto__ refers to function.prototype. Where does Function’s own __proto__ point to?
Function is the constructor of all functions, but Function is also a Function, and its __proto__ should point to its constructor’s prototype. But that’s not what it looks like.
Print finds Function’s __proto__ pointing to Function’s prototype. This leads to philosophical thinking in JS, which came first, the chicken or the egg? Or is Function the god of JS, who not only constructs other functions, but also creates itself?
Conclusion:
- To access a property of an object, first look itself up, if not, will access the object
__proto__
, down the prototype chain, all the wayObject.prototype.__proto__
. - Every function has it
prototype
Property that points to the function’s prototype object. - The prototype object of all functions
__proto__
That will pointObject.prototype
. - Every object has it
__proto__
Property that points to the prototype object of the object’s constructor. - Reference type values to their
__proto__
Will point to the prototype of the corresponding constructor. - Some built-in constructors, such as
Object, Array, String, Boolean
, their__proto__
Property, pointing toFunction.prototype
. Function.__proto__
Point to theFunction.prototype
.- The end of the prototype chain is
Object.prototype.__proto__
That is null.
Attached below is a full prototype chain diagram from the web. If this picture makes sense, then you know the prototype chain, and you know the relationship of all the objects in JS.