


Analysis of an interview question on javascript prototype chain (details)
The content of this article is an analysis (detailed) of an interview question about the JavaScript prototype chain. It has certain reference value. Friends in need can refer to it. I hope it will be helpful to you.
In the face of the basics, all skills are in vain.
The question is like this
Requires writing the output of the console.
function Parent() { this.a = 1; this.b = [1, 2, this.a]; this.c = { demo: 5 }; this.show = function () { console.log(this.a , this.b , this.c.demo ); } } function Child() { this.a = 2; this.change = function () { this.b.push(this.a); this.a = this.b.length; this.c.demo = this.a++; } } Child.prototype = new Parent(); var parent = new Parent(); var child1 = new Child(); var child2 = new Child(); child1.a = 11; child2.a = 12; parent.show(); child1.show(); child2.show(); child1.change(); child2.change(); parent.show(); child1.show(); child2.show();
The knowledge points involved in the question
this Points to
Prototype machine prototype chain
Inheritance of class
Primitive type and reference type Difference
Each knowledge point can be taken out for separate special research.
Details of knowledge points needed to solve the problem
1. Constructors have a prototype attribute, pointing to the prototype object of the constructor, and the instances will share the same A prototype object;
2. When an instance is generated, a new heap memory will be generated in the memory. General operations on the instance will not affect other instances, because they occupy different spaces in the heap memory and do not affect each other. ;
3. Each instance has an implicit prototype __proto__ that points to the prototype object of the constructor;
4.This pointing problem, common situations include the following:
4.1 When used as an object method, it points to whoever calls it (this question mainly involves this)
4.2 When called as a function, it points to the global top-level variable window
4.3 As a constructor When a function is called, that is, when the new operator generates an instance, this in the constructor points to the instance
4.4 In the call and apply methods, the binding of the specified this is displayed as the specified context
5. Literal Quantitative method (there is also information that translates literal into direct quantity. I personally think that the latter translation is actually more intuitive and more vivid). When assigning objects and arrays (the essence of arrays is also objects), they are all references, that is, resources are generated in the heap memory. The stack memory generates variables, and then the variables point to the address of the resource.
6. The search rules of the prototype chain follow the shortest path principle, that is, first search for the instance attributes, and then search for the specified attributes along the prototype chain until Object.prototype and null at the end of the prototype chain. If the instance itself and If the property being searched does not exist in the entire prototype chain, undefined will be returned
7. The detailed difference between assignment statements for primitive value assignment and reference type assignment.
Start analyzing the question
1.parent.show()
There is basically nothing to explain.
You can get the answer by directly taking the value1 [1,2,1] 5
;
2.child1.show()# The constructor of
##Child was originally pointing to
Child. In the question,
Child
is explicitly set to The prototype object of the class points to an instance of the Parent
class, which is one of the common inheritance methods
in JavaScript object-oriented programming. It should be noted here that Child.prototype
points to the instance Parent, not to the class Parent
You can directly output the answer on the console to get
11 [1,2,1] 5
This is surprising What’s confusing is why the last column of the array pointed to by this.b is
1 instead of
11?
Let’s first take a look at what child1 looks like:
When the child1.show() method is executed, since child1, as an instance of Child, has the attribute a, so this.a in the show() method will directly point to the value of this attribute, also It is 11, and will not continue along the prototype chain to get the a attribute on the object pointed to by __proto__;
Then look for this.b. Since child1 does not have the attribute b, it will go along the prototype chain. Get the b attribute on parent, its value is an array, the first two items are constants, nothing to say, the last item of the array is a reference, and the pointer here is not a dynamic pointer, because in new Parent() In one step, it has been executed once, and it is determined to point to the resource pointed by parent.a, which is the resource pointed to by the a attribute in child1.__proto__, which is the value 1.
It should be noted that:
From the code point of view, the child1.__proto__.b array The three items point to child1.__proto__.a. If we modify the value of child1.__proto__.a at this time, will it affect the result of child1.show():
-
The answer is that it has no impact. Why do properties that seem to point to the same address have different values? Because when the parent instance is generated, this.a points to a primitive value 2, so the third item in this.b is actually assigned a primitive value, so it looks like a reference type assignment at first glance, but it is not. . Primitive value assignment will open up new storage space, making the values of this.a and this.b[2] equal, but pointing to different addresses in the heap memory. For more detailed explanations, please see the blog posts recommended in [Extended Reading].
2. How to make the third item of the child1.__proto__.b array also output 11?
Because in In the Parent class definition, the third item of the b attribute array points to the value of the a attribute, which means that this reference is dynamically pointed to before the Parent is instantiated, so as long as the value of this.a in the class definition is changed before the Parent is instantiated, , you can achieve the desired effect. If it has been instantiated in Parent, you can only explicitly modify the value of the *.b[2] attribute.
Modify after instantiation
Another way is to set the get/set method for the a attribute. Yes, whenever the value of the a attribute changes, the value of b[2] is modified synchronously. The code and running results are as follows:
-
If you understand the above explanation, then the same answer can be obtained here: 12 [1,2,1] 5##3.child2.show( )
Then the code is executed: child1.change(); child2.change();
4.parent.show()
parent is an instance of the Parent class, and Child.prorotype points to another instance of the Parent class. The two are two resources in the heap memory and do not affect each other. Therefore, the above operations do not affect the parent instance.
The output results remain Unchanged: 1 [1,2,1] 5;5.child1.show(),child2.show()
What changes happened after child1 executed the change() method?
this.b.push(this.a)
Due to the dynamic pointing characteristics of this, this.b will point to the b array on Child.prototype, and this.a will point to the a attribute of child1, so Child.prototype.b becomes It becomes [1,2,1,11];
this.a = this.b.length
The points of this.a and this.b in this statement are the same as The previous sentence is consistent, so the result is that child1.a becomes 4;
this.c.demo = this.a
Because child1’s own attributes do not have c attribute, so this.c here will point to Child.prototype.c. The value of this.a is 4, which is a primitive type. Therefore, the value will be assigned directly during the assignment operation, Child.prototype.c. The result of demo is 4, and this.a then increases to 5(4 1 = 5).
Then, child2 executes the change() method, Both child2 and child1 are instances of the Child class, so their prototype chains point to the same prototype object Child.prototype, which is the same parent instance, So all the effects in child2.change()
Statements to the prototype object will affect the final output result of child1
this.b.push(this.a)
Because The dynamic pointing feature of this, this.b will point to the b array on Child.prototype, this.a will point to the a attribute of child2, so Child.prototype.b becomes
[1,2,1, 11,12];
this.a = this.b.length
The directions of this.a and this.b in this statement are consistent with the previous sentence, so the result is child2.a becomes 5;
this.c.demo = this.a
Since child2’s own attribute does not have the c attribute, this.c here will point to Child.prototype.c, so the execution result is that the value of Child.prototype.c.demo becomes the value of child2.a, 5, and child2.a eventually increments to 6 (5 1 = 6).
Next, execute the output command, and the final result will be output:
child1.show():5 [1,2,1,11,12] 5
child2.show() :6 [1,2,1,11,12] 5
Extended thinking
When I was solving the problem, I made an error in this.c.demo = this.a. I thought there would be something wrong here. A reference is passed, but a value is actually passed. After analysis, it is understood that because this.a points to an original value, it is equivalent to assigning the original value to the object attribute, so the value of child.c.demo will not be affected after the assignment. The impact of changes to child.a. If child.a is a reference type, what will the result look like?
We make some modifications to the source code and point child.a to an object (i.e. reference type): 
Then after running, we will find that the value of Child.prototype.c will follow the value of child1.a Changes with changes, because the value of child1.a is a reference type at this time, and the assignment process will make Child.prototype.c and child1.a point to the memory space address of the same resource. For a more detailed explanation of original types and reference types, you can refer to the blog in Extended Reading at the end of this article.
Harvest and Reflection
1. Basic knowledge is originally scattered details, and must be learned with the mentality of fighting to the end.
2. Basic knowledge is the most boring thing, and it is also what really widens the gap between people. It is also the threshold that you must cross if you want to enter a big factory. It is important but not urgent. We are also novices. Some people will become front-end architects after 3-5 years. Some people will still use endless new frameworks to bind events to buttons after 3-5 years. Whoever you want to be depends on how much effort you have to put in. , most of the time there is nothing wrong with it. The foundation is very important! Very important! Very important!
Due to the dynamic pointing characteristics of this, this.b will point to the b array on Child.prototype, and this.a will point to the a attribute of child1, so Child.prototype.b becomes It becomes [1,2,1,11];
The points of this.a and this.b in this statement are the same as The previous sentence is consistent, so the result is that child1.a becomes 4;
Because child1’s own attributes do not have c attribute, so this.c here will point to Child.prototype.c. The value of this.a is 4, which is a primitive type. Therefore, the value will be assigned directly during the assignment operation, Child.prototype.c. The result of demo is 4, and this.a then increases to 5(4 1 = 5).
child2.change()
Statements to the prototype object will affect the final output result of child1
The directions of this.a and this.b in this statement are consistent with the previous sentence, so the result is child2.a becomes 5;
Since child2’s own attribute does not have the c attribute, this.c here will point to Child.prototype.c, so the execution result is that the value of Child.prototype.c.demo becomes the value of child2.a, 5, and child2.a eventually increments to 6 (5 1 = 6).
child1.show():5 [1,2,1,11,12] 5
child2.show() :6 [1,2,1,11,12] 5
When I was solving the problem, I made an error in this.c.demo = this.a. I thought there would be something wrong here. A reference is passed, but a value is actually passed. After analysis, it is understood that because this.a points to an original value, it is equivalent to assigning the original value to the object attribute, so the value of child.c.demo will not be affected after the assignment. The impact of changes to child.a. If child.a is a reference type, what will the result look like?
We make some modifications to the source code and point child.a to an object (i.e. reference type):

Then after running, we will find that the value of Child.prototype.c will follow the value of child1.a Changes with changes, because the value of child1.a is a reference type at this time, and the assignment process will make Child.prototype.c and child1.a point to the memory space address of the same resource. For a more detailed explanation of original types and reference types, you can refer to the blog in Extended Reading at the end of this article.
The above is the detailed content of Analysis of an interview question on javascript prototype chain (details). For more information, please follow other related articles on the PHP Chinese website!

JavaScript is widely used in websites, mobile applications, desktop applications and server-side programming. 1) In website development, JavaScript operates DOM together with HTML and CSS to achieve dynamic effects and supports frameworks such as jQuery and React. 2) Through ReactNative and Ionic, JavaScript is used to develop cross-platform mobile applications. 3) The Electron framework enables JavaScript to build desktop applications. 4) Node.js allows JavaScript to run on the server side and supports high concurrent requests.

Python is more suitable for data science and automation, while JavaScript is more suitable for front-end and full-stack development. 1. Python performs well in data science and machine learning, using libraries such as NumPy and Pandas for data processing and modeling. 2. Python is concise and efficient in automation and scripting. 3. JavaScript is indispensable in front-end development and is used to build dynamic web pages and single-page applications. 4. JavaScript plays a role in back-end development through Node.js and supports full-stack development.

C and C play a vital role in the JavaScript engine, mainly used to implement interpreters and JIT compilers. 1) C is used to parse JavaScript source code and generate an abstract syntax tree. 2) C is responsible for generating and executing bytecode. 3) C implements the JIT compiler, optimizes and compiles hot-spot code at runtime, and significantly improves the execution efficiency of JavaScript.

JavaScript's application in the real world includes front-end and back-end development. 1) Display front-end applications by building a TODO list application, involving DOM operations and event processing. 2) Build RESTfulAPI through Node.js and Express to demonstrate back-end applications.

The main uses of JavaScript in web development include client interaction, form verification and asynchronous communication. 1) Dynamic content update and user interaction through DOM operations; 2) Client verification is carried out before the user submits data to improve the user experience; 3) Refreshless communication with the server is achieved through AJAX technology.

Understanding how JavaScript engine works internally is important to developers because it helps write more efficient code and understand performance bottlenecks and optimization strategies. 1) The engine's workflow includes three stages: parsing, compiling and execution; 2) During the execution process, the engine will perform dynamic optimization, such as inline cache and hidden classes; 3) Best practices include avoiding global variables, optimizing loops, using const and lets, and avoiding excessive use of closures.

Python is more suitable for beginners, with a smooth learning curve and concise syntax; JavaScript is suitable for front-end development, with a steep learning curve and flexible syntax. 1. Python syntax is intuitive and suitable for data science and back-end development. 2. JavaScript is flexible and widely used in front-end and server-side programming.

Python and JavaScript have their own advantages and disadvantages in terms of community, libraries and resources. 1) The Python community is friendly and suitable for beginners, but the front-end development resources are not as rich as JavaScript. 2) Python is powerful in data science and machine learning libraries, while JavaScript is better in front-end development libraries and frameworks. 3) Both have rich learning resources, but Python is suitable for starting with official documents, while JavaScript is better with MDNWebDocs. The choice should be based on project needs and personal interests.


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

Dreamweaver Mac version
Visual web development tools

ZendStudio 13.5.1 Mac
Powerful PHP integrated development environment

SAP NetWeaver Server Adapter for Eclipse
Integrate Eclipse with SAP NetWeaver application server.

DVWA
Damn Vulnerable Web App (DVWA) is a PHP/MySQL web application that is very vulnerable. Its main goals are to be an aid for security professionals to test their skills and tools in a legal environment, to help web developers better understand the process of securing web applications, and to help teachers/students teach/learn in a classroom environment Web application security. The goal of DVWA is to practice some of the most common web vulnerabilities through a simple and straightforward interface, with varying degrees of difficulty. Please note that this software