JS Bubbling and Closure case analysis

Source: Internet
Author: User

Background:

today, browse the Web page found Baidu know on an interesting JS problem, the question is actually quite simple, understand point front-end development technology should be able to achieve. Questioner's request: to implement a submenu popup, the menu has a total of three levels, each level menu display has 500 milliseconds of delay. The questioner then posted his question code.

I'll take a look at the code I put on someone else, as long as it's not particularly complicated. After all, the programmer communication, the source code is the best language, just start to see his code is a little feel what is wrong. After careful analysis of the next, it is really interesting to find. If the sensory analysis process is more boring, you can see the conclusion directly.

Here's his code:


    The above code, we take out the JS section to study the following:

onload = function () {var lis = document.getelementsbytagname ("li"), var t = 0;for (var i = 0; i < lis.length; i++) {lis[ I].timer = Null;lis[i].onmouseover = function () {me = This;me.timer = SetInterval (function () {if (me.children[0]) {Me.chil Dren[0].style.display = "Block"}},}lis[i].onmouseout = function () {clearinterval (Me.timer) this.children[0]? This.children[0].style.display = "None": 0;}}}

    first, throw away the most basic errors, such as setting a delay with settimeout.

Problem:

I think a lot of people should have the same problem with me: Move the mouse to the submenu after the first level menu should execute the onMouseOut method, then the submenu should be hidden. But in fact, if the mouse moved quickly, the submenu has a "flashing" phenomenon but eventually can be displayed, but the level three menu is not displayed.

Questions:

is the onmouseout method not implemented? With this question, I added a console.log to the onmouseout and onmouseover methods, and the breakpoint was debugged. The results found a meaningful phenomenon.

the onmouseout method does execute, that is, the submenu is the Style property has changed to none, but the console displays, the execution order of the corrective method: parent Menu onmouseout submenu onmouseover–> parent Menu onmouseover–> child node onmouseout–> parent node onmouseout

Reason:

There are three main reasons for the above problems:

(1) JS execution is time-consuming, especially setting the style display is to cause the reconstruction of the render tree, so the interface will not find changes inside.

(2) The onmouseover function of the questioner is to deliberately set a 500 millisecond delay to perform the display function.

(3) The browser's event model is bubbling execution.

Analysis:

Of course the above reasons, translated adult words are:

when the mouse moved to the submenu, the browser to execute the parent menu onmouseout, this time the sub-menu is required to be hidden, but for the 1th reason, the submenu is not hidden, our mouse moved to the level two menu. This time the browser needs to trigger the onMouseOver method on the level two menu, then execute the onmouseover method of the submenu, and set the delay function, because we do not block the event bubbling, the level two menu onmouseover bubbles to the first level menu, Executes the onmouseover of the parent menu.

Analysis to the above, we should be aware that the level two menu onmouseover should be the submenu (Level three menu) displayed. But we should note that the logic of onmouseover is not a normal logic, but a delay. So the show function of the level two menu (that is, that anonymous function) is executed after the onmouseover function of the first-level menu, so the Me closure variable is changed. Through debugging, you can find me this variable is mounted under Windows, then it is a global variable, the submenu of the onmouseover set it as the child node itself, but then bubbling to the parent node, onmouseover this becomes the parent node itself, So the final show function is executed two times, two times the ME variable is the corresponding node of the parent menu.

The above question is somewhat similar to the resource competition for multithreaded programming in high-level programming languages such as Java, in high-level programming languages, in order to synchronize a resource (variable, object), the language itself provides a keyword similar to synchronized. Of course, we are not multi-threading here, we can't synchronize this variable (the solution later).

then analysis, the back of the two onmouseout, actually better understand, when the program is executed here, the browser finally completed the render tree reconstruction, the submenu is hidden, and then the browser think our mouse moved out of the submenu, So start the onmouseout event of the submenu, and it is bubbling execution, the specific process does not do analysis.

After the program executes two times onmouseout, certainly does not spend 500ms, unless your machine is particularly old, so this time, we set two delay function to be triggered. Then perform the display of the child node of me, we mentioned above two times the show function of the me is actually the same variable, all pointing to the parent menu corresponding to the node. So the child node is displayed.

Here, our problem comes again, onmouseout inside call cleartimeout, then two delay function should be canceled AH. The answer is, cleartimeout usage is wrong. Believe that a lot of people and landlord I like, and did not put JS as a complete technical study, so we know settimeout and setinterval, know with the corresponding clear method to cancel. But we never looked at its operating mechanism (which is, of course, not necessary at all, just like when Java came out, very few people cared about the JVM level). Here we do not delve into, only to give a conclusion, from the world-class can be known. Both SetTimeout and SetInterval return a string (similar to the thread ID), and when the clear method is called, the corresponding ID needs to be passed in order to stop the execution of the deferred function.

The last question, since the submenu has been hidden in the display process, then why the browser triggered onmouseout did not trigger onmouseover again, thus forming a dead loop, so that the page dead? As to this question, I also did not find the standard answer, perhaps the browser for the mouse event triggered by the pixel trigger, we did not move the mouse, naturally will not trigger onmouseover.

Conclusion:

a bunch of crap, a lot of people should be impatient, to tell the conclusion.

(1) JS programming, we must pay attention to event bubbling, bubbling is a good thing, but to be cautious to use, event bubbling can let us improve the efficiency of the program, such as table operation, many times we will let the event bubble to table and then operate, so that can be very efficient execution. The event handling of jquery is a good use of bubbling.

(2) Careful use of closures, JS programming, closures can easily cause memory leaks, cautious use, and the closure variable is easily referred to as a resource competition object, especially in the delay function, it is easy to get confused problems.

(3) Clearinterval and cleartimeout must pass in SetInterval and settimeout return ID, otherwise it is not possible to cancel the delay normally.

(4) Onmouseenter and OnMouseLeave can be used as a solution to the above problems, but the compatibility issue should be noted! Onmouseenter and OnMouseLeave do not do event bubbling, onmouseover and onmouseout will bubble to the parent node, and this point will also change.

Ps:

today, a bunch of nonsense, analysis of the case is meaningless, just bored. "Superficial understanding" is a philosophy of study, but "Trace the way" is the solution to the problem. It is far easier to give the right answer than to find the cause of the problem.

  

JS Bubbling and Closure case analysis

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.