A difficult JavaScript problem

Source: Internet
Author: User

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

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.