This article describes in detail a javascript interview question that is easily overlooked, if you are interested, you can refer to this question as the last question in a set of front-end interview questions. It is used to assess the comprehensive JavaScript capabilities of the interviewer. Unfortunately, it will be nearly two years since then, almost no one can answer the question completely. It is not difficult because most interviewers despise him too much.
The questions are as follows:
Function Foo () {getName = function () {alert (1) ;}; return this ;} Foo. getName = function () {alert (2) ;}; Foo. prototype. getName = function () {alert (3) ;}; var getName = function () {alert (4) ;}; function getName () {alert (5 );} // write the following output: Foo. getName (); Foo (). getName (); new Foo. getName (); new Foo (). getName (); new Foo (). getName ();
The answer is:
Function Foo () {getName = function () {alert (1) ;}; return this ;} Foo. getName = function () {alert (2) ;}; Foo. prototype. getName = function () {alert (3) ;}; var getName = function () {alert (4) ;}; function getName () {alert (5 );} // Answer: Foo. getName (); // 2 getName (); // 4Foo (). getName (); // 1 getName (); // 1new Foo. getName (); // 2new Foo (). getName (); // 3new new Foo (). getName (); // 3
This question is integrated with my previous development experience and various JS pitfalls. This topic involves many knowledge points, including variable definition escalation, this pointer pointing, operator priority, prototype, inheritance, global variable contamination, object attributes, and prototype attribute priority.
This question contains seven small questions, respectively.
Question 1
First, we define a function named Foo, and then create a static property named getName For Foo to store an anonymous function, then, an anonymous function named getName is created for the prototype object of Foo. Then, a function named getName is created through the function variable expression, and a function named getName is declared.
In the first question, Foo. getName naturally accesses the static attribute stored on the Foo function. Naturally, it is 2 and there is nothing to say.
Question 2
Second, call the getName function directly. Since it is called directly, it is to access the current getName function in the scope above, so it has nothing to do with 1 2 3. Countless interviewees answered this question as 5. There are two pitfalls: Variable declaration escalation and function expression.
1. Variable declaration escalation
That is, all declared variables or declared functions are promoted to the top of the current function.
For example, the following code:
console.log('x' in window);//truevar x;x = 0;
When the code is executed, the js engine promotes the declaration statement to the top of the code and changes it:
var x;console.log('x' in window);//truex = 0;
2. function expressions
Both var getName and function getName are declaration statements. The difference is that var getName is a function expression, while function getName is a function declaration. For details about the various function creation methods in JS, refer to the classic JS closure interview questions that most people will do wrong.
The biggest problem with function expressions is that js splits the code into two lines for separate execution.
For example, the following code:
Console. log (x); // output: function x () {} var x = 1; function x (){}
The actual code is to split var x = 1 into var x; and x = 1; and then convert var x; and function x () {} two rows are upgraded to the top:
var x;function x(){}console.log(x);x=1;
Therefore, the final function declared x overwrites the variable declared x, and the log output is the x function.
Similarly, the code in the original question is:
Function Foo () {getName = function () {alert (1) ;}; return this ;}var getName; // only raise the variable declaration function getName () {alert (5) ;}// raise the function declaration to overwrite the var declaration Foo. getName = function () {alert (2) ;}; Foo. prototype. getName = function () {alert (3) ;}; getName = function () {alert (4) ;}; // The final value will overwrite the function getName statement getName (); // final output 4
Third question
In the third question, Foo (). getName (); First executes the Foo function, and then calls the getName attribute function of the returned object of the Foo function.
The first getName = function () {alert (1) ;}; of the Foo function is a function value assignment statement. Note that it has no var declaration, therefore, the getName variable is first searched for within the scope of the current Foo function. No. Search for whether the getName variable is contained in the upper-level function scope, that is, the alert (4) function in the second question, assign the value of this variable to function () {alert (1 )}.
The getName function in the outer scope is modified.
NOTE: If it is still not found, the window object will be searched up. If there is no getName attribute in the window object, a getName variable will be created in the window object.
The Return Value of the Foo function is this, and many articles have been introduced in the blog about this in JS.
In short, the point of this is determined by the method in which the function is called. The direct call method here points to the window object.
Then the Foo function returns the window object, which is equivalent to executing window. getName (), while the getName in the window has been changed to alert (1), so it will output 1
Two knowledge points are discussed here. One is the scope of variables, and the other is the this point.
Fourth Question
Directly call the getName function, which is equivalent to window. getName (). Because the variable has been modified when the Foo function is executed, the result is the same as that of the third question, which is 1.
Fifth Question
The fifth question is "new Foo. getName ();". Here we examine the operator priority of JavaScript.
By checking the table above, we can know that the priority of the vertex (.) is higher than that of the new operation, so it is equivalent:
New (Foo. getName )();
Therefore, the getName function is actually executed as the constructor. Then, 2 is displayed.
Question 6
Question 6: new Foo (). getName (). First, we can see that the operator priority brackets are higher than new. The actual execution is
(New Foo (). getName ()
Then execute the Foo function first, while Foo has returned values as the constructor at this time. Therefore, we need to describe the constructor return values in js.
Return Value of the constructor
In traditional languages, constructor should not return values. The actual returned values are the instantiated objects of the constructor.
In js, constructor can return values or not.
1. If no value is returned, the instantiated object is returned in the same way as other languages.
2. If a return value exists, check whether the return value is of the reference type.If it is a non-reference type, for example, the basic type (string, number, boolean, null, undefined) is the same as the non-return value, the actual returned instantiated object is returned.
3. If the return value is of the reference type, the actual return value is of this reference type.
In the original question, this is returned, and this originally represents the current instantiated object in the constructor, then the final Foo function returns the instantiated object.
Then, call the getName function of the instantiated object. Because no attribute is added to the Foo constructor, The getName is found in the prototype of the current object.
Finally, output 3.
Question 7
Question 7: new Foo (). getName (); is also an operator priority.
The actual execution is:
New (new Foo (). getName )();
Initialize the instantiated object of Foo and use the getName function on its prototype as the constructor to create a new object.
The final result is 3.
Last
In terms of the answer, 100% of the first question can be answered correctly, and 50% of the second question can be answered correctly. The third question is not answered correctly, and the fourth question is rarely answered correctly. In fact, this question is not widely used and may be used in some scenarios. Most people should be correct only when they have one to two years of work experience.
It can only be said that some people are too impatient and despise. I hope you can understand some js features through this article.