Last time to share a problem, we have a good response, very happy to write something that someone is willing to take the time to see, but also to their own great encouragement, in fact, although not more than the actual programming, but also can let you find some of the language level you did not notice the problem. So, share a slightly more difficult JavaScript topic this time.
function Foo() {GetName= function () {Console.Log(' 1 '); }; Return This;}Foo.GetName= function () {Console.Log(' 2 ');};Foo.Prototype.GetName= function () {Console.Log(' 3 ');};VarGetName= function () {Console.Log(' 4 ');};functionGetName() {Console.Log(5);}Foogetname (); Getname (); foo (). Getname (); new foo. Getnamenew foo (). new new foo (). getname ()
What is the output of the above code in the browser environment? Let's find out the final answer:
2 4 1 1 2 3 3
The first four difficulty is not very big, mainly is the latter three, basically is annihilated, sigh is really too around. After the analysis of a bit, say it one by one. First, one must pay attention to a problem
function Foo () { GetName = function () { Console. ' 1 ' }; return this; /span>
The getName
variable declared inside the function, preceded by no var
, let
, const
, so actually according to LHS ( This introduction can go to my blog to see a summary of LHS and RHS, the declaration of GetName
is at the global scope (and window
). Second, you need to be clear whether you know the result of the following code in the browser:
var GetName = function () { Console. ' 4 ' }; function Getname () Span class= "pun" >{ Console.5}getname ();
The result of the preceding code is: 4
. The reason for this is that the variables and function declaration function
declared by var
are promoted, but the promotion level of the function declaration is higher than the var
, so the actual execution result of the above code is:
function GetName () { Console.5}var GetName = function () { Console. ' 4 ' }; getname ()
The latter function expression getName
overrides the previous function declaration getName
, actually executing a function expression (that is, why JavaScript never has a function overload so to speak), so the output is 4
. First I add the necessary comments to the following code:
function declarationfunction Foo() { Global variablesGetName= function () {Console.Log(' 1 '); }; Return This;}Add a property getname to a function whose type is function, so it can be seen here that function is also an objectFoo.GetName= function () {Console.Log(' 2 ');};Add a method to the prototype Foo GetNameFoo.Prototype.GetName= function () {Console.Log( ' 3 ' ); }; var GetName = function () { Console. ' 4 ' }; function Getname () Span class= "pun" >{ Console.5 /span>
The following executes the first statement:
Foo.getName();
The function Foo
itself is not executed, the function is performed by the property getName
, of course the output is: 2
. Next Execute:
getName();
This is done in the global scope getName()
, there are two corresponding getName
declarations, according to the level of ascension mentioned above, the actual execution is the function expression:
var getName = function () { console.log(‘4‘);};
So the output is 4
. Next execution
Foo().getName();
First, take a look at the JavaScript operator precedence, from high to low sort from the above can be seen ()
with the .
same priority, so Foo().getName()
from left to right execution. First run Foo()
, the global is getName
overwritten as output console.log(‘1‘)
, and the return this
is represented at this time window
. Then the equivalent of execution window.getName()
, then the actual output is 1
(overwritten). Here we go.
getName();
This is needless to say, the implementation is: 1
(and the above a hair). Here are the three hardest parts:
new Foo.getName();
There are two possible ways to execute this statement:
(new Foo).getName()
Or
new (Foo.getName)()
But according to the operator precedence table we can tell that the .
operator is actually new
higher than the priority, so the actual execution is the second, so it is
Foo.getName = function () {console.log(‘2‘);};
The function performs the new
operation, of course the output is 2
. Down to the execution
new Foo().getName();
There are two possibilities for this statement:
(new Foo()).getName();
Or
new (Foo().getName)();
So what's that supposed to be? I thought it would be the second way of execution, the first way to find out the real execution is through browser debugging. I see that the author of the topic explains this:
First look at operator precedence brackets above new. The actual execution is (new Foo ()). GetName (). The Foo function is executed first.
I think the above explanation is problematic, in contrast to the above two execution methods, the first is to execute first new
, then execute the .
operator, and then execute the ()
. The second is to execute first ()
, then execute .
, and then execute the new
operator. If you really judge by what you refer to as a priority, you should actually perform the second rather than the first. Then finally found the reason, the original appeared before the more JavaScript priority table is not complete, Magnum MDN gives the most authoritative JavaScript precedence table operator precedence I list the most important part (from high to low): So with the parameters of the new
Operator is the highest priority, there is no problem, the order of execution should be the first. Then it is easy to follow it, and the (new Foo()).getName();
(new Foo())
new generated object is returned, the object has no getName()
method, so the method is prototype
found in getName()
. So the output is 3
. Victory is in sight, let's take a look at the last question.
new new Foo().getName();
In the same way as in the previous step, we analyze how the statement is executed by the priority table. First, the operator with the parameter has the new
highest precedence, the first step is divided into:
new (new Foo().getName)();
The second step is divided into:
new ((new Foo()).getName)();
So the execution (new Foo()).getName
of this function is the corresponding Foo.prototype.getName, so the execution of the new (Foo.prototype.getName)()
positive output is 3
. hahaha, so difficult to finally solve the problem, happy ~ Summarize it, first JavaScript knowledge is best to go to MDN, if other places to write the wrong really is Hairenbujian. Secondly, if the code is written in the use of the operator is less than the priority of this thing, once the ambiguity of the place immediately used ()
, the code of readability is really important! It's important! It's important! After all, the code is still for people to see ~
A difficult JavaScript problem