Articles Catalogue
I. Prototype
brief introduction
- Each function object has a prototype attribute, which by default points to an empty Object instance object (called a prototype object).
- There is a constructor attribute in the prototype object that points to the current function object
Code example:
function Test() {} Test.prototype.say = () => { console.log('Say Hello'); } const t1 = new Test(); const t2 = new Test(); Test.prototype.say = () => { console.log('Say Hello'); } console.log("Prototype objects:", Object.keys(Test.prototype)); // [], indicating that the prototype object of a function is an empty object console.log(Test.prototype.constructor === test); // true, specifying the constructor property of the prototype object, which points to the current function object
Explicit Prototype and Implicit Prototype
- Each function has a prototype attribute, an explicit prototype
- Each instance object has a _proto_ attribute, which is an implicit prototype.
- The value of the implicit prototype of the instance object is equal to the value of the explicit prototype of the corresponding function.
function Test() {} const t1 = new Test(); console.log(Test.prototype); // An empty object containing _proto_ and constructor attributes (pointing to Test) console.log(t1.__proto__); // An empty object containing _proto_ and constructor attributes (pointing to Test) console.log(Test.prototype === t1.__proto__); // true
Implementation mechanism of explicit prototype and implicit prototype
- Function prototype property: automatically added when defining a function, default value is an empty Object object
- Object's _proto_ attribute: automatically added when creating an object, default value is the constructor's prototype attribute value
- Developers usually modify prototypes by manipulating the prototype attributes of functions
Prototype Supplement
- The object pointed to by the explicit prototype of a function is an empty Object object by default (except for Object, the prototype of Object is not an empty object and has no _proto_ attribute)
- So the prototype object of Object is the end of the prototype chain, and the prototype of the prototype object of Object is null.
function Test() {} const o = {}; const t = new Test(); console.log(o.__proto__); // Object object containing multiple methods, without _proto__attribute console.log(t.__proto__); // Empty object console.log(o.__proto__.__proto__); // null
- Each function object has both an implicit prototype and an explicit prototype.
- All functions are instances of Function (including Function itself)
- The implicit prototype of each function is the same instance object
- The only function object whose implicit prototype equals explicit prototype is Function.
function Test() {} function Hello() {} console.log(Test.prototype); // Empty object console.log(Test.__proto__); // ƒ () { [native code] } console.log(Hello.prototype === Test.prototype) // false console.log(Hello.__proto__ === Test.__proto__); // true console.log(Hello.__proto__ === Function.__proto__); // true console.log(Function.prototype === Function.__proto__); // true
2. Prototype Chain (Alias: Implicit Prototype Chain)
concept
-
When accessing the properties of an object
- Search in its own properties first, find the return
- If not, look up the _proto_ chain and find the return.
- If not, return undefined
-
Role: Query object properties
Object Reading and Writing
- When reading an object's attributes, it automatically searches the prototype chain of the object.
function Person() {} Person.prototype.speak = () => { console.log('Speak Chinese!'); } const p1 = new Person(); const p2 = new Person(); // Each instance object has attributes/methods in the function prototype p1.speak(); // Speak Chinese! p2.speak(); // Speak Chinese!
- When setting the properties of an object, the prototype chain is not looked up. If there is no such property in the current object, add the property directly and set the value.
function Person() {} Person.prototype.name = 'Xiao Ming'; const p1 = new Person(); const p2 = new Person(); // When reading attributes, they are looked up from the current object and the prototype chain console.log(p1.name); // Xiao Ming // When setting attributes, modify attributes on the current object directly, if not on the current object, add attributes directly without modifying attributes on the prototype chain. p2.name = 'Xiaohong'; console.log(p1.name); // Xiao Ming console.log(p2.name); // Xiaohong
- Methods are generally defined on the prototype, and attributes are generally defined on the object itself through constructors.
Extension: Principle of instanceOf Operator
- a instanceOf C: If the explicit prototype of C is on the implicit prototype chain of a, return true, otherwise return false
function A() {}; function B() {}; function C() {} // Assign the prototype of C to the prototype of B, and the prototype of B to the prototype of A. These two lines of code cannot be reversed. B.prototype = C.prototype; A.prototype = B.prototype; const a = new A(); console.log(a instanceof C);
3. Explanation of Examples
1. Example 1
function A() {} A.prototype.n = 1; // The prototype of the object is assigned to the display prototype of the function when the object is initialized, so the implicit prototype of b is {n: 1}. const b = new A(); A.prototype = { n: 2, m: 3 } // For the same reason, the implicit prototype of c is {n: 2, m: 3}; const c = new A(); console.log(b.n, b.m, c.n, c.m); // 1 undefined 2 3
Example 2
function Test() {} Object.prototype.a = function() { console.log('a Method execution'); } Function.prototype.b = function() { console.log('b Method execution'); } var t = new Test(); /** * Here's a wave of explanations * 1,The explicit prototype of each function object points to an empty object, while the implicit prototype of each instance object === the explicit prototype of the function object. * Then t.a() will be looked up in this order: T. proto == Test. prototype = {}; {}. proto == Object. prototype; * The explicit prototype of Object has method a, so it can be executed correctly. * 2,t.b() Similarly, there is no method b found in the prototype chain, so there will be an error: t.b is not a function; * 3,Test.a() The search order of test. _proto_=== Function. prototype= {b: function () {console. log ('b method execution');}; * {b: fucntion() {console.log('b Method execution';}. _proto_=== Object. prototype; * Therefore, both Test.a() and Test.b() can be executed correctly. */ t.a(); // a(); t.b(); // t.b is not a function Test.a(); // a(); Test.b(); // b();
IV. SUMMARY
-
Each function object (except Object function object) has an explicit prototype object by default, pointing to an empty Object object, with a constructor attribute in the empty object, pointing to the current function object.
-
All function objects have an implicit prototype object (including Function function objects), and all of them default to an explicit prototype object of Function function objects.
-
The explicit prototype of function object is equal to the implicit prototype of instance object.
-
When accessing object attributes, the instance object itself will be searched first, then returned if found, then continued searching if not found in the implicit prototype chain, then returned if found, and undefined if not found.
-
Additionally, the implicit prototype of the function object has nothing to do with the display prototype (except for the Function object), and the explicit prototype of the Function object equals its own implicit prototype (because all functions are instances of Function (including Function itself).
Recommended Links
See before This blog There are detailed prototype chain sketches. Interested friends can take a look at them in detail.
An example gives you a thorough understanding of prototype objects and prototype chains