“This is the third day of my participation in the November Gwen Challenge. See details of the event: The last Gwen Challenge 2021”.
preface
This question was invented by Ali a few years ago and has caused job interview disaster. You may be able to say the result, but you may not be able to say the cause.
I looked up part of the explanation of this question, and many of them just finished in a daze, not grasping the core of the problem at all. Therefore, Ah Bao also offered his own understanding, hoping to add a vote for the right side, so that people can search for the right side more frequently.
Here is the original Ali question and explanation:
Portal: Ali subject link
The title
function test() {
getName = function() {
Promise.resolve().then(() = > console.log(0));
console.log(1);
};
return this;
}
test.getName = function() {
setTimeout(() = > console.log(2), 0);
console.log(3);
};
test.prototype.getName = function() {
console.log(4);
};
var getName = function() {
console.log(5);
};
function getName() {
console.log(6);
}
test.getName();
getName();
test().getName();
getName();
new test.getName();
new test().getName();
new new test().getName();
Copy the code
Analysis of the
This topic covers a lot of topics, such as scopes, precompilation, prototypes and prototype chains, new, and event loops.
Let’s first analyze what the first half of the problem actually does:
- define
test
function - for
test
The function creates a static methodtest.getName
- for
test
The function creates an instance methodtest.prototype.getName
- Defining global variables
getName
After the program runs, it is assigned to a function - Defining global functions
getName
test
Function internals to global variablesgetName
Assigns a new value and returns a value ofthis
Compared with the original topic, the current topic adds the knowledge of event loop, Promise. Then and setTimeout are both asynchronous tasks, the former is a micro task, the latter is a macro task.
parsing
precompiled
- Function precompiled tetralogy and global precompiled trilogy
- Variable declaration, declaration promotion, function declaration, overall promotion
GO: {
test: fn,
getName: function getName() { console.log(6); }}Copy the code
test.getName()
Execute the static method test.getName on the test function, print 3, and the setTimeout callback is inserted into the event queue, waiting for the synchronization task to complete
getName()
Before getName executes, getName has been reassigned to console.log(5), printing 5
test().getName()
test()
Execute globallytest
Function to modify the globalgetName
Value;test()
Functions are executed in default binding, non-strict modethis
Point to thewindow
, the return value iswindow
GO: {
test: fn,
// Change the global getName value
getName: function() {
Promise.resolve().then(() = > console.log(0))
console.log(1);
};
}
Copy the code
test().getName()
Equivalent to carrying outwindow.getName()
, the callGO
In thegetName
,Promise.then
Press into the microtask queue and print1
getName()
Execute the global function getName(), printing 1, promise.then to press the microtask queue
(⭐) New knowledge supplement
Let’s add a little bit of knowledge about the new operator before we go through the rest of the problem.
First let’s look at the description of new in MDN. The syntax is:
new constructor[([arguments])]
Copy the code
([arguments]) means that by default, new constructor(… Args) and New constructor, and the former takes precedence over the latter. More detailed priorities are shown below:
As you can see from the figure above, some of the priorities are as follows:New (with argument list) = Member access = function call > new(without argument list)
new test.getName()
From left to right, there are three operators: new with no argument list, member access, and function call.
Operators of the same priority are executed from left to right, so member access is performed first to get the static method getName on the test function.
After member access, the expression changes to new (test.getName)(), the new operator changes from no argument list to argument list, executes from left to right, treats test.getName as a constructor, and generates the corresponding instance.
New (test.getName)() executes, prints 3, setTimeout callback presses into the macro task queue.
new test().getName()
The expression operators from left to right are: new with argument list, member access, function call
- perform
new test()
:new
Binding,this
Point to an instance. new
Not on the build instancegetName
Property, found along the prototype chaintest.prototype.getName
Properties, print4
new new test().getName()
Expression operators from left to right are: new with no arguments, new with arguments, member access, function call
So the expression can be converted to the form: new((new test()).getName())
new test().getName
: access to thetest.prototype.getName
attributenew new test().getName()
To:test.prototype.getName
For the constructor, print4
Promise.then
Execute the promise.then in the microtask queue, there are two promises. then, and print two zeros
setTimeout
Execute the setTimeout callback in the macro task queue, printing two 2s
The answer
3
5
1
1
3
4
4
0
0
2
2
Copy the code
Past wonderful articles
- Cow guest latest front-end JS written test 100 questions
- Grab the latest front end test five hundred data analysis JS interview hot spots
- Native JavaScript soul torture (2), can you answer all correctly?
- Native JavaScript soul Test (1), how much can you answer?
- A thorough understanding of prototypes and prototype chains in JavaScript
- JavaScript precompilation learning
- Complete understanding of EventLoop in JavaScript
- “2W word big chapter 38 interview questions” completely clear JS this pointing to the problem
After the language
If you feel that this article is of some help to you, I hope you can give a thumbs-up to encourage Bao, Bao will continue to work hard. In addition, if this article has a question, or do not understand part of the article, you can reply to me in the comment section, we come to discuss, learn together, progress together!
If you feel confused in the comments section, you can also add my wechat or QQ for detailed communication, and the name is battlefield small bag.